C 使用套接字通信在标准输出上打印的剩余字符
在套接字TCP通信中,我有一个服务器和一个客户端。两者都可以读取和写入套接字 代码是用C编写的,使用Linux系统调用C 使用套接字通信在标准输出上打印的剩余字符,c,linux,sockets,tcp,system-calls,C,Linux,Sockets,Tcp,System Calls,在套接字TCP通信中,我有一个服务器和一个客户端。两者都可以读取和写入套接字 代码是用C编写的,使用Linux系统调用recv和write recv将收到的字符串保存在: char message_array[2000]; 另一个维度相同的数组用作写入过程的源 读取和写入过程完成后,执行以下操作以清除所有数组元素: memset(&message_array, 0, sizeof(message_array)); 此外,在每次写入和每次读取过程中,对stdin和stdout执行ffl
recv
和write
recv
将收到的字符串保存在:
char message_array[2000];
另一个维度相同的数组用作写入过程的源
读取和写入过程完成后,执行以下操作以清除所有数组元素:
memset(&message_array, 0, sizeof(message_array));
此外,在每次写入和每次读取过程中,对stdin
和stdout
执行fflush
服务器在其stdout
上打印其写入的内容和接收的内容
如果我从两个终端发送小消息(“hello”、“hi”),即使发送了几次(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
显示为实际消息后的尾随字符,这只是一个长短语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;
}
这两个函数在成功创建新的套接字连接后(因此,在成功创建accept
后),在main
中作为线程使用pthread\u create
调用。它们显然在同一个插座上工作
我的问题是:
1) 这是软件问题还是套接字问题
2) 除了memset
和fflush
之外,我应该遵循哪个技巧
在重复使用之前,读取端不会将用于读取的缓冲区归零。Dochar remote_message[MAX_STRING_LEN]={0}代码>在声明时间和memset(远程消息,0,sizeof(远程消息);
读取后
memset(&local\u message,0,sizeof(local\u message));
-->memset(local\u message,0,sizeof(local\u message));
请记住TCP(您正在使用TCP吗?)不是面向消息的协议。read()
可以(并且最终将)返回1字节到写入程序迄今为止发送的数据量之间的任何数据量。如果您想要面向行的协议/输出,请扫描读取的数据中的“\n”,不要在scanf()
中删除它
其他:
- 您是否在某个位置对套接字描述符调用
close()
- 为什么要释放
int*
参数?它们真的是用malloc从堆中分配的吗
在重复使用之前,读取端不会将用于读取的缓冲区归零。在声明时执行char remote\u message[MAX\u STRING\u LEN]={0};
,在读取后执行memset(remote\u message,0,sizeof(remote\u message);
memset(&local\u message,0,sizeof(local\u message));
-->memset(local\u message,0,sizeof(local\u message));
请记住TCP(您正在使用TCP吗?)不是面向消息的协议。read()
可以(并且最终将)返回1字节到写入程序迄今为止发送的数据量之间的任何数据量。如果您想要面向行的协议/输出,请扫描读取的数据中的“\n”,不要在scanf()
中删除它
其他:
- 您是否在某个位置对套接字描述符调用
close()
- 为什么要释放
int*
参数?它们真的是用malloc从堆中分配的吗
在connection\u-handler\u-read()
中,您读取strlen()
字符,而不memset()
缓冲到'\0'
strlen()
字符是您在connection\u-handler\u-write()中发送的全部内容
并且它不计算尾随的'\0'
。读取端的缓冲区可能包含一些未初始化的字符。在连接处理程序\u read()
中,您读取strlen()
字符,而不memset()
缓冲到'\0'
strlen
connection\u handler\u write()中只发送字符
并且它不计算尾随的'\0'
。在读取端缓冲区中可能包含一些未初始化的字符。有两件事让我感到很突出:第一件事是你说你在写入/读取后调用memset
?第二件事是执行fflush(stdin)
在技术上是未定义的行为。此外,请尝试向我们展示您用于发送、接收和打印的代码,最好尝试创建一个用于向我们展示的代码(据说一张图片可以表达千言万语,代码也是如此)。@JoachimPileborg是的,我在读/写后调用memset
,所以(出于我的意图)当数组的内容不再有用,需要清除时。整个程序,即使很小,也太长,但我将尝试至少包括读写例程。'printf(远程消息)调用了一个不保证以null结尾的缓冲区。Cargo cult memset没有正确地使用send/recv返回的值来插入终止null。可能其他错误集中在对以null结尾的字符数组的误解上。@MartinJames可能是由于您的经验,您将大量信息集中在几行代码中首先:如果write\u size
是write
返回的值,我是否应该执行memset(&local\u message,0,write\u size);
?您的意思是数组remote\u message
不能为空