Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用套接字通信在标准输出上打印的剩余字符_C_Linux_Sockets_Tcp_System Calls - Fatal编程技术网

C 使用套接字通信在标准输出上打印的剩余字符

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

在套接字TCP通信中,我有一个服务器和一个客户端。两者都可以读取和写入套接字

代码是用C编写的,使用Linux系统调用
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
之外,我应该遵循哪个技巧

  • 在重复使用之前,读取端不会将用于读取的缓冲区归零。Do
    char 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
    不能为空