LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   Unpredictable behaviour with send/recv system call (http://www.linuxquestions.org/questions/programming-9/unpredictable-behaviour-with-send-recv-system-call-894712/)

rajeshwar27singh 07-30-2011 09:48 PM

Unpredictable behaviour with send/recv system call
 
Hi,

I am making a library, but I am facing a strange problem while sending data over network using ethernet.

I am sending 39 bytes of the data from one server to slave application but some time slave receives 39 bytes and some time it receives 29 bytes. And when ever slave receives 29 bytes all the memories to which my pointers are pointing get changed.

This problem is only when I am sending data from the server to slave, while sending data from slave to server I am facing no such issue.

Have anybody faced such issue before.

Regards,
Rajeshwar Singh Bisht

paulsm4 07-30-2011 10:15 PM

Quote:

I am sending 39 bytes of the data from one server to slave application but some time slave receives 39 bytes and some time it receives 29 bytes
You are NOT guaranteed to get all the data that was written all at once. You should read in a loop, until all expected data is received, or until an error occurs.

Quote:

And when ever slave receives 29 bytes all the memories to which my pointers are pointing get changed.
Sounds like buffer overrun.
Q: Are you sure you're allocating enough space for the data buffer?
Q: Are you interpreting the data read correctly? For example, perhaps you're expecting "0x0a" (10), but you're receiving "0x0a00" (2560)?
Q: Have you stepped through under the debugger, and looked at the actual bytes being received (which you receive 29 bytes, instead of the expected 39)?

Web31337 07-30-2011 10:16 PM

Well, what's the actual problem here? Test your networking hardware first.
And you have to ensure received data is correct and full in your application, it's a logical programming question. Your application MUST be ready for such unpredicatble behaviour.
Take good care of memory, please.

jschiwal 07-31-2011 01:34 AM

Moved: This thread is more suitable in the Programming Forum and has been moved accordingly to help your question get the exposure it deserves.

rajeshwar27singh 07-31-2011 04:27 AM

@paulsm4: Thanks for the reply. I have allocated enough memory for the data to be received. If we think logically, if memory is big enough for 39 bytes it should also work with 29 bytes but that is whats not happening.

I also tried looping around the send and recv call and tried sending data 1 byte at a time. There is still data loss and interestingly its always first 10 bytes which go missing. Although after looping even though I am still getting 29 bytes instead of 39 bytes but my pointers are not changing their address which works with me.

The string which I am supposed to receive is in following format:
"<two string with no spaces in them and separated by _>:<pid of the application>:<hostname>"
eg "slave_master:2134:mylaptop"
where : are my delimiters.

When I change the following string "<two string with no spaces in them and separated by _>" I found that slave only receive last 4 characters of this string, if this string is of 10 bytes then first 6 bytes go missing and if it is of 14 bytes then first 10 bytes go missing.

As per the application requirement I do need require the first part before the first delimiter but I would be thankful to you if you could help me with it.

Regards,

JohnGraham 07-31-2011 05:21 AM

I'd use Wireshark to see what's happening on the network, and that'll show you if your server is sending all the data correctly - then use a debugger to step through the code around the server's send()/the client's recv(), as appropriate. Although I suspect your problem is with the client's recv() - and since you also see pointers getting changed, this definitely sounds like some sort of memory corruption. When using the debugger, trace all calls around the recv() and try and find out when things get changed.

dwhitney67 07-31-2011 06:14 AM

Quote:

Originally Posted by rajeshwar27singh (Post 4429792)
When I change the following string "<two string with no spaces in them and separated by _>" I found that slave only receive last 4 characters of this string, if this string is of 10 bytes then first 6 bytes go missing and if it is of 14 bytes then first 10 bytes go missing.

Can you please show how you are declaring the buffer for the string, how you are putting it together to form "master_slave:port:host", and then lastly, how you are sending it?

rajeshwar27singh 08-01-2011 05:23 AM

I am using sprintf to join 4 different kind of data into a string. Size of
void identitydata[1024 * 4];
sprintf (identitydata, "%s:%d:%s:%s:%s", indentifier, MasterPid, hostname, ip, port);

This string is then stored into a file. All the data is getting stored into the file properly and when read back it is retrieved back properly.

fscanf(inputfile, "%s", data)

for sending data I have used the following loop.

for (counter = 0; counter < size; counter++){
if ((error = send (recvfd, &regdata[counter], sizeof(char), 0)) == -1){
perror ("Error in Sending data");
exit(1);
}
}

JohnGraham 08-01-2011 05:44 AM

Quote:

Originally Posted by rajeshwar27singh (Post 4430512)
sprintf (identitydata, "%s:%d:%s:%s:%s", indentifier, MasterPid, hostname, ip, port);

I would urge you to use snprintf(), just in case you unexpectedly end up with a huge string somewhere.

Have a look at what's going on over the network with Wireshark - there really is no substitute for this. Then debug the function going wrong (like I said, it sounds like the recv() part of your client).

dwhitney67 08-01-2011 06:39 AM

Quote:

Originally Posted by rajeshwar27singh (Post 4430512)
I am using sprintf to join 4 different kind of data into a string. Size of
void identitydata[1024 * 4];
sprintf (identitydata, "%s:%d:%s:%s:%s", indentifier, MasterPid, hostname, ip, port);

This string is then stored into a file. All the data is getting stored into the file properly and when read back it is retrieved back properly.

fscanf(inputfile, "%s", data)

for sending data I have used the following loop.

for (counter = 0; counter < size; counter++){
if ((error = send (recvfd, &regdata[counter], sizeof(char), 0)) == -1){
perror ("Error in Sending data");
exit(1);
}
}

Here's some more questions...

1. How is 'data' declared?
2. How does the string within 'data' end up in 'regdata'?
3. Why are you sending one character at a time via the socket, instead of sending the entire string?
4. I'm not sure how 'regdata' is declared, but it would seem that you are sending the address of the value (character) within 'regdata'. Perhaps the & is not required?

A suggestion:
Code:

char data[1024];

/* read data from file... */

/* send data */
size_t bytes_sent = 0;

while (bytes_sent < strlen(data))
{
  ssize_t ret = send(sock, data + bytes_sent, strlen(data) - bytes_sent, 0);

  if (ret > 0)
  {
      bytes_sent += ret;
  }
  else if (ret < 0)
  {
      if (errno == EINTR || errno == EAGAIN)
        continue;

      perror("Failure to send.");
      break;
  }
}


theNbomr 08-01-2011 11:23 AM

Quote:

Originally Posted by paulsm4 (Post 4429659)
You are NOT guaranteed to get all the data that was written all at once. You should read in a loop, until all expected data is received, or until an error occurs.

This seems like the most obvious cause, and I wonder why the rest of the thread seems to have deviated from it. If the data needs to be sent as a complete datagram, perhaps the application requires the protocol UDP, rather than TCP. Especially for such small packet sizes, this seems like the most obvious solution. There is no way to force TCP to packetize data in any particular way. It is a stream oriented protocol, and only guarantees that the data will be received in the same order that it was sent. It does not guarantee anything about the size of the chunks that will be used along the way.

--- rod.


All times are GMT -5. The time now is 10:44 PM.