Click to See Complete Forum and Search --> : socket programming help


cesarsalad
December 20th, 2004, 02:48 PM
i am programming in linux using sockets, and i have downloaded several socket classes, but none of them do what i want to do. since i am new to linux sockets, that's why i downloaded classes. i've tried to learn the protocol, but i don't see anything for the problem that i have. i liked the winsock style socket on VB. on data arrival, it calls the DataArrival function and I can read the data just by calling getdata.
the problem is that when i call the "recv" function of the linux sockets, it seems as if it doesn't read all the data. the size of the data that i have and the size that it says it read sometimes do not match up when the data is being sent very quickly, i.e. thousands of bytes in less than a second; in winsock this is not a problem because the dataarrival event is called for every packet, but with linux sockets it seems like sometimes it concatenates packets together and doesnt read all of them. i don't know what to do.. i tried using MSG_WAITALL in recv but that just waits till the whole buffer fills up, and i've looked online and haven't found a solution..

what i can do in dataArrival in winsock is something like

socket.getdata strbuf
while len(strbuf) <> bytesTotal
do events
wend

but any while loop in c++ like this freezes the program

Richard.J
December 20th, 2004, 05:40 PM
my advise is to forget about all that VB stuff and get back to the basics.
For TCP sockets, you can't be sure to receive the same amount of bytes that have been sent by a call to send() from the remote side with one call to recv(). the reason for this is that the buffer being sent can be fragmented by either the sending TCP stack or along the way to the receiver. The only thing you can do is to put some information of the message length into the message itself. A usual way is to send a header that start with, say, an int (4 bytes) indicating the message length. Consecutevi calls to recv() until this message length is at least reached (the total amount of bytes of the message can be exceeded after one call or the other) will give you the whole message.

An ex.
say your message being sent is x bytes long. It starts with 4 bytes indicating the length. So the receiving side only knows that the first 4 bytes of a message indicate its length. you do a recv() (in a loop) until you receive at least 4 bytes. Evaluate these 4 bytes and you know how much bytes you need to receive to get a complete message. Loop on recv() until you received at least x bytes, putting the received bytes in a buffer. If you received more than x bytes, you received more than one message an you need to start over again.

I hope this is not too theoretical. I normally don't write responses this long.
For socket programming, I would recommend W. Richard Stevens: UNIX network programming.
Even though it has the UNIX in its title, it can be used for Windows as well. Forget about the WSA... stuff ;-)

A good link on the net is http://www.tangentsoft.net/wskfaq

HTH
Richard

cesarsalad
December 20th, 2004, 05:50 PM
thanks for your help.. the problem is im using these sockets to connect to a remote server with its own interface and encryption. the message length is a part only of specific instructions, and each packet has an arbitrary number of instructions... i did all this code with winsock and it worked perfectly. are you sure there's no easy way to do this? how does winsock do it?

Richard.J
December 20th, 2004, 06:03 PM
well, the only point I see is that in your VB example, you use bytesTotal. Where does it come from? This should be the value that indicates the message length you expect. Basically, all socket operations (even the ones on higher levels) must know how long a message would be to make sure the complete message is received. That is, you must be sure to know the underlying protocol. You can't connect to a FTP server and expect your program to run correctly if it does not understand the FTP protocol. Maybe you can post a sample of your code to illustrate your problem?

I will be off to bed right now, but I will be back tomorrow ...

Richard

cesarsalad
December 20th, 2004, 06:32 PM
bytesTotal is an argument of the dataArrival method, i guess somehow it knows how many bytes to expect...\

i'll post some code in a bit

EDIT:

so i'm using the PracticalSocket.cpp and .h that I found online somewhere.. the source is here:
http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/practical/PracticalSocket.cpp

my code that receives is:


try
{
TCPSocket client_socket (GAMESERVER, 11999 );
char reply[RCVBUFSIZE + 1];
while(1)
{
try
{
bytesReceived = client_socket.recv(reply, RCVBUFSIZE);
cerr << "RECEIVED REPLY " << bytesReceived << endl;
reply[bytesReceived] = '\0';
repstring = reply;
ProcessReply(client_socket, repstring, bytesReceived);
}
catch ( SocketException& ) {}
}
}
catch ( SocketException& e )
{
std::cout << "Exception was caught:" << e.what() << "\n";
}


repstring is a string from string.h
ProcessReply processes this string every time recv is called. but it doesnt seem to fill in completely.

actually, is it possible that doing repstring = reply would cutoff the string at some point if reply contained 0 characters? i.e. ASCII zeros (because the data should). hmm maybe thats the problem

Andreas Masur
December 21st, 2004, 04:29 AM
[ Moved thread ]

Richard.J
December 21st, 2004, 04:59 AM
There must be a possibility for ProcessReply to determine that the string it processes is complete. If you receive 0 bytes it means that the socket has been closed by the remote party. If your server application works this way: accept an incoming socket, send some data, then close the socket again, then you could determine the completeness of the message when the socket is closed. You should check that.

Richard