0

I'm working on a C project that implements a TCP client-server. The sockets and the send() functions i'm using are the one defined in the libraries sys/socket.h and winsock2.h.

My problem is that when i try to send multiple strings one after the other, some messages aren't transmitted correctly, with some data (sometimes all the message) that goes missing. The following code, for example, works without a problem when i'm running server and client on the same machine, but if I try to run it with a remote server, then the third message isn't properly received.

Client Side

    char message[1024];  
    memset(message, 0, 1024);  
    fill_message(message, msg1); //A function that prints something in the message string. 
                                 //It may fill less than 1024 characters.
    send(clientSocket, message, 1024,0);
    
    fill_message(message, msg2);
    send(clientSocket, message, 1024,0);
    
    fill_message(message, msg3);
    send(clientSocket, message, 1024,0);

Server Side

    char message[1024];
    memset(message, 0, 1024);
    recv(clientSocket, message, 1024,0);
    print_and_do_stuff(message);

    recv(clientSocket, message, 1024,0);
    print_and_do_stuff(message);

    recv(clientSocket, message, 1024,0);
    print_and_do_stuff(message);

Note: the string message may not be exactly of length 1024.

My solution has been to make the client wait for 1 second by calling sleep(1) after each message is sent. Is this the proper way to address the issue? Or am i missing something about how send() and recv() work?

More in general: what is the "proper" way to program with sockets? Should I maybe be sending the message byte-by-byte and specifying the length as the first thing? If someone could point me toward a good tutorial/guide on what the best practices are when working with sockets, I'd be happy to read it.

R_marche
  • 3
  • 4
  • 'If someone could point me toward a good tutorial/guide on what the best practices are when working with sockets' oh, that's easy - SO 'sockets' tab, esp. the FAQ. You know - the Q&A about TCP byte streams, correctly and completely handling returns from syscalls like send/recv and correct use of C library calls that demand NUL-terminated char arrays as arguments. – Martin James Jun 10 '22 at 08:44
  • @MartinJames I'm not sure if i understand correctly your comment: In the send/recv [documentation](https://pubs.opengroup.org/onlinepubs/000095399/functions/send.html) that i found it doesn't specify that arguments need to be nul terminated. Also, was [this](https://stackoverflow.com/questions/16945345/differences-between-tcp-sockets-and-web-sockets-one-more-time) the FAQ you were talking about? Searching TCP byte streams under the 'socket' tag just shows this one – R_marche Jun 10 '22 at 09:14
  • In short: You are assuming that a `send` exactly matches a `recv`. This assumption is wrong for TCP, since TCP is only byte stream without inherent message boundaries. It does not matter if C, Python or whatever is used. – Steffen Ullrich Jun 10 '22 at 09:34
  • @SteffenUllrich Ok, and the fact that it the program works when i tell the sender to "wait" before start sending again is just due to the fact that the receiver has time to properly receive and stop the `recv` execution? – R_marche Jun 10 '22 at 09:47
  • When you tell the sender to wait it is more likely that the recipient will be able to catch with the sender. This also means that the senders socket buffer will be mostly empty and that a single `send` will be able to put all data into the buffer. If you would have actually checked the return code of `send` you might have noticed that not all data were written in some cases. – Steffen Ullrich Jun 10 '22 at 09:53

1 Answers1

0

Socket functions may or may not read/send the entire data in one call, which means that you have to verify the correct reception server side, and maybe create a custom protocol on top of TCP to keep track of the size you sent and received. TCP, contrary to UDP, guarantees the integrity of data, meaning that you won't lose anything when sending, but you may need to use multiple function calls to ensure all of the data has been sent and red. As for good tutorial and guides, as someone already said in comments, you can find loads of examples and guides about it.

Nastor
  • 638
  • 4
  • 15