在套接字TCP通信中,我有一个服务器和一个客户端。两者都可以读取和写入套接字。
代码是用C语言编写的,使用Linux系统调用recv
和write
。
recv
将收到的字符串保存在:
char message_array[2000];
另一个具有相同维度的数组用作write
进程的源。
在读取和写入过程之后,执行以下操作,以清除所有数组元素:
memset(&message_array, 0, sizeof(message_array));
此外,在每次写入和每次读取过程中,fflush
和stdin
都会执行stdout
。
服务器在其stdout
上打印它写的内容和收到的内容。
如果我从两个终端发送小消息(“你好”,“嗨”),即使多次(18-20),所有似乎都能正常工作。但是,如果我尝试发送更长的消息(超过5个字符,但短于2000!),服务器端有一些奇怪的行为:它打印从客户端收到的消息,但随后插入随机数的尾随字符以前的消息。例如,我有:
CLIENT MESSAGE: hello1
SERVER MESSAGE: hello2
CLIENT MESSAGE: hello3
SERVER MESSAGE: hello4
CLIENT MESSAGE: some other characters5
SERVER MESSAGE: hello6
CLIENT MESSAGE: a long phrase 7
ters5
在几条消息之后,上一个消息中的5个字符ters5
在实际消息之后显示为尾随字符,仅为a long phrase 7
。
继续“对话”,其他意外的换行符和“旧”字符出现在服务器的stdout
上。
读写例程的代码如下:
void *connection_handler_read(void *socket_read_desc)
{
int read_sock = *(int*)socket_read_desc;
int read_size;
char remote_message[MAX_STRING_LEN];
while( (read_size = recv(read_sock, remote_message, MAX_STRING_LEN, 0)) > 0 )
{
printf(remote_message);
fflush(stdout);
}
free(socket_read_desc);
connection_active = 0;
return 0;
}
void *connection_handler_write(void *socket_write_desc)
{
int write_sock = *(int*)socket_write_desc;
char local_message[MAX_STRING_LEN];
while( connection_active != 0 )
{
scanf ("%[^\n]%*c", local_message);
write(write_sock, local_message, strlen(local_message));
memset(&local_message, 0, sizeof(local_message));
fflush(stdin);
}
free(socket_write_desc);
return 0;
}
在成功创建新的套接字连接之后,main
中的这两个函数作为带pthread_create
的线程调用(因此,在成功accept
之后)。它们显然在同一个插座上运行。
我的问题是:
1)这是软件问题还是套接字问题?
2)除了memset
和fflush
之外,我应该遵循哪种技巧?
答案 0 :(得分:2)
在重新使用之前,读取端不会将用于读取的缓冲区归零。宣言时char remote_message[MAX_STRING_LEN] = {0};
和阅读后memset(remote_message, 0, sizeof(remote_message);
。
memset(&local_message, 0, sizeof(local_message));
- > memset(local_message, 0, sizeof(local_message));
请记住TCP(您使用的是TCP吗?)不是面向消息的协议。 read()
可以(并最终将)返回1个字节与编写器到目前为止发送的数量之间的任何数据量。如果您需要面向行的协议/输出,请扫描读取数据'\ n'并且不要在scanf()
中将其删除。
其他:
close()
?int *
参数?它们是否真的从具有malloc的堆中分配?答案 1 :(得分:2)
在connection_handler_read()
中,您阅读了strlen()
个字符,而memset()
没有缓冲到'\0'
。您在strlen()
中发送的所有字符都是connection_handler_write()
个字符,并且不计入尾随'\0'
。在读取端缓冲区可能包含一些未初始化的字符。