【问题标题】:Using threads to handle multiple read/writes from sockets?使用线程来处理来自套接字的多个读/写?
【发布时间】:2016-12-07 00:58:40
【问题描述】:

我正在尝试创建两个程序一个客户端和服务器,其中客户端打开一个套接字连接,然后将数据写入服务器,服务器在接受连接时会产生一个新线程,然后将其分离,以处理其余的读取/写。问题是,当我进行多次写入然后从客户端读取时,读取并没有得到正确的数据,但是在服务器端它打印出它发送了正确的数据。

这就是我的代码生成新线程的样子,以及我如何处理这些线程。

while(1){
    listen(sockfd,5);

    // determine the size of a clientAddressInfo struct
    clilen = sizeof(clientAddressInfo);
    int *newsockfd = malloc(sizeof(int));
    // block until a client connects, when it does, create a client socket
    *newsockfd = accept(sockfd, (struct sockaddr *) &clientAddressInfo, &clilen);
    // if the connection blew up for some reason, complain and exit
    if (*newsockfd < 0){
        error("ERROR on accept");
    }
    connection_args *args = malloc(sizeof(connection_args));
    args->file_descrp = newsockfd;
    pthread_t tid;
    pthread_create(&tid,NULL, handle_connect, args);
}

void * handle_connect(void* args){
    connection_args* connect_arg = (connection_args*)args;
    pthread_detach(pthread_self());
    int n = -1; 
    char buffer[256];
    bzero(buffer,256);
    //while not close;
    while(1){
        // try to read from the client socket
        n = read(*connect_arg->file_descrp,buffer,255);
        printf("input: %s\n", buffer);
        // if the read from the client blew up, complain and exit
        if (n < 0){
            error("ERROR reading from socket");
        }
        int fd;
        if(strcmp("open",buffer) == 0){
            fd = open("file.txt",0);
            bzero(buffer,256);      
            sprintf(buffer,"%d",fd);
        }else if(strcmp("read",buffer) == 0){
            char *read_buffer = malloc(sizeof(char)*256);
            bzero(read_buffer,256);
            fd = read(get_filedescrp(),read_buffer,30);
            bzero(buffer,256);
            sprintf(buffer,"%s,%d",read_buffer,fd);

        }else if(strcmp("close",buffer) == 0){
            break;
        }
        printf("buffer_send: %s\n",buffer);
        // try to write to the client socket
        n = write(*connect_arg->file_descrp,buffer,sizeof(buffer));
        // if the write to the client below up, complain and exit
        if (n < 0){
            printf("here!!\n");
            error("ERROR writing to socket");
        }
        bzero(buffer,256);
    }
    printf("Left thread\n");
    return NULL;
}

【问题讨论】:

  • 一般来说,我建议使用 Wireshark 和 Netcat 来调试网络代码。 Wireshark 当然会让你看到你发送的内容,你可以使用nc 作为一个已知的工作服务器和客户端,这样你就可以隔离你的服务器和客户端,减少你一次处理的变量数量。
  • 不要在 accept() 循环中调用 listen()。在进入循环之前调用它一次。并且不需要malloc() 你的套接字描述符。在使用它执行空终止操作之前,您不会空终止您的buffer,例如printf()strcmp()。您也没有考虑到 TCP 是一种流传输,不能保证 read() 将接收完整的字符串,它有时可以(并且可能会)接收部分数据。您需要在发送端分隔命令并在读取端查找那些分隔符。
  • 在客户端调用 read() 两次然后得到正确的数据。我将如何解释 TCP 是流传输这一事实,继续调用 read() 直到我得到非空响应?另外关于空终止字符,如果发送带有空终止字符的字符串,我是否需要在阅读后手动重新添加它?

标签: c multithreading sockets


【解决方案1】:

如果没有某种协议,您将无法通过 TCP/IP 实现客户端服务器通信。发送方写入的数据可以在此过程中被切片和切块,并以不同的块长度进入阅读器端。在尝试解释数据之前,您必须有办法判断您是否收到了完整的帧。

例如,您可以使用一个非常简单的基于行的协议:读取数据直到并包括'\n' 字节。一次将一个字节读入留置权缓冲区的效率有点低,但很容易实现。

【讨论】:

    【解决方案2】:

    套接字读取调用可能会或可能不会返回客户端在单个调用中发送的全部数据。 每个读取调用返回在该调用中读取的字节数。所以应用程序应该在循环中调用 read,直到读取到预期的字节数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-02
      • 1970-01-01
      • 2016-08-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多