Problem with RecvRaw

Hi,

I am trying to use the TSocket class to comunicate to a server that is written using the Linux normal socket library.
The version of ROOTthat I am using is v3.10.02.
I have a problem when I want to read information back from the server. So I have at the client (ROOT) side:
TSocket *fSock;
fSock=new TSocket(server, port);
char buffer[40];
int length_client=sizeof(buffer), l_received;
l_received=fSock->RecvRaw(buffer, length_client);

Server side (normal c code). Socket is open using socket, bind, listen, accept, routines.
char buffer[40];
int length_server;
// creation of socket
length_server = size of the buffer to be sent;
send(client_socket, buffer, length_server, 0);

If the length_equal is equal to length_server there is no problem. But if the length_client is bigger than length_server, meaning that I don’t know before hand the size of the message being sent, the RecvRaw method stays blocked, but the send on the server side returns no error. When the server closes the client socket then the RecRaw method is unblocked and also gives the correct response, both in the l_received and the data inside the buffer.
Is not possible to receive data without knowing its size using RecvRaw ?

Regards,
Paulo

Paulo,

Are you setting the length of the message on the server side. The convention is that the first 4 bytes of the message contain the length of the buffer.
See example in TSocket::Send and TMessage::SetLength

Rene

Hello,

in the server side I am not using the ROOT library. I used the Linux socket library. So the message being sent doesn’t have the size in the first 4 bytes.
Reading more carefully inside the ROOT RecvRaw method, I’ve found out that it that can only receive the exact amount of bytes defined in the call of the method.
However the socket library allows the reception of messages from a socket without prior knowledge of the size of the message.
Is it possible to implement that in the RecRaw method ?

Regards,
Paulo

Hello Paulo,

You can set the socket to non-blocking on the client side
and monitor it with select: it will then get what the server
sends, whatever the length.

Something like this:

TSocket *fSock = new TSocket(server,port);
fSock->SetOption(kNoBlock, 1);
char buffer[40] = {0};
TMonitor *mon = new TMonitor;
mon->Add(fSock);
TSocket *fSockRead = mon->Select();
fSockRead->RecvRaw(buffer,sizeof(buffer));
printf("%s (errno: %d)\n",buffer,gSystem->GetErrno());

gSystem->GetErrno() will return EAGAIN (=11), because
in principle there might be other info to be received; so,
if you expect more you should loop until you get all the
bytes you expect.

As an alternative, you can have a look at the file
rpdutils/src/net.cxx: it contains examples of functions
to send and receive messages in a non-ROOT environment
correctly interfaced with TSocket::Recv and TSocket:Send
functions.

Hope it helps.

Kind regards,

Gerri Ganis