Reputation: 91
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
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
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
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
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
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