收到套接字c字节,但我无法打印字符串

时间:2013-05-04 13:32:06

标签: c sockets printf recv

我使用此代码从C客户端的Java服务器接收String。

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);

例如,当Java服务器发送此String

  

bZzrEcyVEmjmIf

我得到了这个结果

  

recv()'用buf字符串中的16字节数据:

所以我收到了16个字节,但是

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

不要给我任何东西。

服务器发送了此字符串

  

TYvuDbbKALp3scp

我试过这段代码

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

结果我有

  

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

5 个答案:

答案 0 :(得分:3)

似乎Java正在发送一个长度为前缀的字符串。前两个字节对应于长度字段。这两个字节决定了后面的字节数。这是我如何序列化和打印:

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');

值为0的字节表示字符串的结尾,在C中。这解释了为什么buf指向的字符串似乎为空。它还解释了为什么在长度为前缀的字符串中具有值0的任何嵌入字符都会导致代码中注释掉的printf停止打印字符串。

这是一个没有明确定义的视觉表示的字符值。这解释了为什么长度为前缀的字符串中的嵌入字符会导致fwrite打印看起来很难看的字符。

答案 1 :(得分:2)

你确定你的角色是可打印的吗?

使用类似的内容查看您收到的内容:

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

答案 2 :(得分:0)

发送的字符串包含14个字符。如果C应用程序收到16个字节,则有2个额外字节。可能它们被放置在缓冲区的开头并记下发送字符串的长度(这是我在TCP套接字上发送字符串的方式,因为不保证在那里保留消息边界)。如果第一个字节为零,你肯定什么都看不见。

尝试从buf打印出所有16个字节的值。

我还建议在实际字符之前发送和解析字符串的长度,然后从socked中读取相应的(已知的)字节数,否则你可能会得到一个不完整的字符串或两个串联的字符串。

答案 3 :(得分:0)

stdout流被缓冲,你的printf应该包含\n来刷新流

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

fflush(stdout); 

答案 4 :(得分:0)

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

然后,一旦你收到缓冲区:

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

请注意发送和使用的缓冲区。 recv意味着携带二进制数据。如果传输的数据是字符串,则需要对其进行管理(即添加'\ 0'和缓冲区结束等)。此外,在这种情况下,您的Java服务器会在协议(客户端需要注意)之后添加长度字节。