0

I am attempting to read and write to a socket using linux networking programming in C. I make successful calls to "write" and "read" in the client and server programs respectively.

The part I am having difficulty understanding is that on my client program, I loop and call the write 5 different times, on the server, I loop and call the read 5 different times.

This is the expected output:

MSG: I got your message MSG: I got your message MSG: I got your message MSG: I got your message MSG: I got your message

This is the actual output:

MSG: I got your messageI got your messageMSG: I got your messageI got your messageMSG: I got your messageMSG: MSG:

As you can see the expected output and the actual output are different. It looks like the client is able to call "write" twice before it is actually sent.

This is what I have for the client code

for(int i=0;i<5;i++)
{   
    int n = write(ssocket.socketFileDescriptor,"I got your message",18);
    cout<<n<<" number of bytes written."<<endl;
    if (n < 0) socketError("ERROR writing to socket");
}

This is the server code:

void* run(void* arg)
{
    ServerSocket* ss = (ServerSocket*)arg;
    //while(true)
    for(int i=0;i<5;i++)
    {
        char buffer[256];
        bzero(buffer,256);
        int n = read(ss->newsockfd,buffer,256);
        printf("MSG: %s",buffer);
    }
    close(ss->newsockfd);
}

This is an addition to the question below which is out of date at this point.

Am I missing a call to flush or something?

Simulate Java's Thread class in C++

Community
  • 1
  • 1
Matthew
  • 3,886
  • 7
  • 47
  • 84
  • 1
    You are assuming that TCP can transfer messages larger than one byte. It can not - it's a byte/octet STREAMING protocol and knows no message-boundaries above one byte. If you want to transfer larger, more complex messages, you need a protocol on top of TCP. There are endless dups of this question - so many that I can't be bothered to look:) – Martin James Aug 29 '14 at 21:08
  • If you're using TCP sockets then everything sent is concatenated into one stream, and when it's read you get what's available at that point (up to the buffer size). You need to insert your own message boundaries and parse the stream in the receiver. – molbdnilo Aug 29 '14 at 21:12
  • So I opened up wireshark and confirmed that each 'write' call actually created it's own packet. So that means that the read is the one where it is doubling up. That is where I saw the 'read' and I said in my code to read 256 bytes. – Matthew Aug 30 '14 at 19:56

1 Answers1

2

Your client and server are just not coordinated. The client writes the message 5 times as quickly as it can, and the server reads five times as quickly as it can. In your example output, evidently on your first call to read() the client has sent the message twice, and on the second call to read() it's sent it a further two times. You read() up to 256 characters, and each time you call it, it will just attempt to read anything that's currently in the buffer. If the client has send multiple messages by that time, read() will just grab everything.

You typically need some type of synchronization, e.g. after you send one message, your client waits for the server to send "OK" or something similar before it sends the second message. Short of that, you can use some kind of end-of-message marker (such as a newline) so the server can differentiate them, if you have a very simple communication format.

Crowman
  • 25,242
  • 5
  • 48
  • 56
  • Or just add buffering on both sides (server & client). – Basile Starynkevitch Aug 29 '14 at 21:12
  • Yes! I would like to add buffering, but I don't exactly know how to do that. I am attempting to create a system similar to Java and all that is built in with the BufferedFileReader or whatever... How do you do buffering? Also, Say like I want to send more that 256 characters with out a response? How do I do that? I assume this socket is using TCP so I shouldn't have to acknowledge in anyway though right? – Matthew Aug 29 '14 at 21:25
  • @Matthew: Your best bet is to use one of the many third party networking libraries out there. Implementing buffering isn't all that hard, but it's not totally trivial, either. You can implement a poor man's version of it by `read()`ing one character at a time until you hit the end-of-line character, for receiving lines of unknown length. Using a system call for single characters is relatively inefficient, but unless you're writing a high volume server the network will probably be the bottleneck. – Crowman Aug 29 '14 at 21:29