user2328999
user2328999

Reputation: 91

Socket c bytes received but I can't print the String

I use this code to receive a String from a Java server in a C client.

if( recv( to_server_socket, &reply, sizeof( reply ), MSG_WAITALL ) != sizeof( reply ) )
{
    printf( "socket read failed");
    exit( -1 );
}

printf( "got reply: %d\n", ntohl( reply ) );

char buf[512];
ssize_t nbytes=0;
int byte_count;

byte_count = recv(to_server_socket, buf, sizeof buf, 0);
printf("recv()'d %d bytes of data in buf\n", byte_count);
buf[byte_count] = '\0';

printf("String : %s\n",buf);

For example, when the Java server sends this String

bZzrEcyVEmjmIf

I got this result

recv()'d 16 bytes of data in buf String :

so I received 16 bytes but the

printf("String : %s",buf);

don't show me anything.

The server sent this String

TYvuDbbKALp3scp

I tried this code

   int i=0;
    while(i<byte_count){
        printf("String : %c\n",buf[i]);
        i++;  recv()'d 17 bytes of data in buf

and for result I have

String : String : String : String : T String : Y String : v String : u String : D String : b String : b String : K String : A String : L String : p String : 3 String : s String : c String : p

Upvotes: 2

Views: 3476

Answers (5)

autistic
autistic

Reputation: 15652

It appears that Java is sending a length-prefixed string. The first two bytes correspond to the length field. These two bytes determine how many bytes follow. Here's how I'd serialise and print that:

unsigned int str_len = buf[0] * 256 + buf[1];
char *str = buf + 2;
/* printf("%.*s\n", str_len, str); // You could use this,
                                      instead of the following two lines: */
fwrite(str, 1, str_len, stdout);
putchar('\n');

A byte with the value 0 denotes the end of a string, in C. This explains why the string pointed to by buf appears to be empty. It also explains why any embedded characters in your length-prefixed string that have the value 0 will cause the commented out printf in my code to cease printing the string.

It's a character value that doesn't have a well-defined visual representation. This explains why embedded characters in your length-prefixed string will cause fwrite to print awkward-looking characters.

Upvotes: 3

Sudhee
Sudhee

Reputation: 714

struct _received_data 
{
    unsigned char len_byte1;
    unsigned char len_byte2;
    char *str;
} received_data;

Then, once your receive the buffer:

received_data *new_buf = (received_data*) buf;
printf( "String = %s", new_buf->str);

Note that the buffers that are used in send & recv are meant to carry binary data. If data being transmitted is a string, it needs to be managed (ie., adding '\0' and end of buffer etc). Also, in this case your Java server is adding length bytes following a protocol (which the client needs to be aware of).

Upvotes: 0

ouah
ouah

Reputation: 145919

Are you sure your characters are printable?

Use something like this to see what you received:

for (int i = 0; i < byte_count; i++)
{
    printf("%02x ", (unsigned int) buf[i]);    
}
printf("\n");  // flush stdout

Upvotes: 3

Miguel Prz
Miguel Prz

Reputation: 13792

The stdout stream is buffered, your printf should include \n to flush the stream

printf("String : %s\n",buf);

or

fflush(stdout); 

Upvotes: 0

nullptr
nullptr

Reputation: 11058

The string being sent contains 14 characters. If the C application receives 16 bytes for it, there are 2 extra bytes. Probably they are placed at the beginning of the buffer and note the length of the string being sent (this is how I would send strings over a TCP socket since message boundaries are not guaranteed to be kept there). And if the first byte is zero, you will surely see nothing.

Try printing out values of all the 16 bytes from the buf.

I would also advise to send and parse a length of the string before the actual characters and then read from the socked the appropriate (known) number of bytes, otherwise you risk to get an incomplete string or two concatenated strings.

Upvotes: 0

Related Questions