1

I was searching for hours to get an answer about my question, but didnt find anything. Maybe I get some help here.

What I'm trying to do: A Java-Client sends a message to a C-Server. The message contains different types like integer, short and also a string (e.g. message = int: total_msg_length; short: operation; string: hello --> total_msg-length=4 (size of integer), operation = 2 (size of short), hello = 5 (each letter is 1 byte=5).

So, how can I receive the message in my server? The code below receives an Integer (works fine). Next step will be to receive a short and then a string (converted in US-ASCII).

int *msg;
int recv_size;
int final_msg;

if( (recv_size = recv(client_socket, &msg, sizeof(msg), 0 )) < 0 ){
    error_exit("Fehler bei recv(message_len)");
}

final_msg = endian_swap(msg);
printf("Message: %d\n", final_msg);

return final_msg;

Is there a way to use a byte array instead of char buffer? Im thankful for every help. Please excuse my bad english, I'm from germany :-)

2
  • 1
    Be careful: you are passing sizeof(msg) instead of sizeof(int). Your code works 'cause both sizes are equal in most platforms, but it is not correct. You want to receive an int, not an int pointer. The size of a pointer is different, in general, to the size of the pointed value. Commented Nov 22, 2013 at 16:22
  • 1
    Closely read the man-pages for recv()/send() and learn that at least for sockets those two functions do not necessarily receive/send as much bytes as they were told to, but few. So looping around such calls counting until all data had been received/sent is a good idea, not to say an essential necessity. Commented Nov 22, 2013 at 16:26

1 Answer 1

2

You need to create a generic "read_n_bytes" function.

This you can use to read the message-size, the operation and the text, in three successive calls.

Those three calls you then wrap in a function to be called to read an entire message.


A generic reader might look like this:

/*
 * Reads n bytes from sd into where p points to.
 *
 * returns 0 on succes or -1 on error.
 *
 * Note: 
 * The function's name is inspired by and dedicated to "W. Richard Stevens" (RIP).
 */
int readn(int sd, void * p, size_t n)
{
  size_t bytes_to_read = n;
  size_t bytes_read = 0;

  while (bytes_to_read > bytes_read)
  {
    ssize_t result = read(sd, p + bytes_read, bytes_to_read);
    if (-1 == result)
    {
      if ((EAGAIN == errno) || (EWOULDBLOCK == errno))
      {
        continue;
      }

#     ifdef DEBUG     
      {
        int errno_save = errno;
        perror("read() failed");
        errno = errno_save;
      }
#     endif

      break;
    }
    else if(0 == result)
    {
#     ifdef DEBUG
      {     
        int errno_save = errno;
        fprintf(stderr, "%s: Connection closed by peer.", __FUNCTION__);
        errno = errno_save;
      }
#     endif

      break;
    }

    bytes_to_read -= result;
    bytes_read += result;
  }

  return (bytes_read < bytes_to_read) ?-1 :0; 
}
Sign up to request clarification or add additional context in comments.

6 Comments

your function is supposed to receive the size of the message to read as argument, so I'm guessing, before calling this function we need to receive the message size from the sender?
@UrbiJr: Correct. Either you know the number of bytes to come or just call readn() twice, once to receive a binary integer with a well defined size from <stdint.h>, let's say uint16_t, and then use this value to another call to readn() to receive a block of exactly this length (or an error).
if you could help it would be greatly appreciated. I'm literally stuck..
@UrbiJr: What about making a real (and complete) question out of this?
@UrbiJr: So why not undelete the question?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.