TCP套接字读/写冻结服务器

时间:2016-12-28 22:35:28

标签: c tcp

我想在C中使用TCP套接字实现协议,这种方式有点像这样:

  1. 客户端连接到服务器并发送它想要的文件名 下载
  2. 服务器读取该值并检查它是否是有效的文件名(服务器上是否存在)+向客户端发送ACCEPTFAILURE状态
  3. 客户端读取该状态并准备下载+发送READY状态到服务器
  4. 服务器发送文件并关闭连接
  5. 服务器代码

    char response[128];
    int bytes_read;
    while ((bytes_read = read(info.socket, response, 128)) > 0) {}
    
    if (valid_request(files, files_count, response)) {
        write(info.socket, MC_ACCEPT, 4);
    } else {
        write(info.socket, MC_FAILURE, 4);
    }
    

    客户代码

    int w_status = write(sck, requested_file, strlen(requested_file));
    if (w_status < 0) {
        fprintf(stderr, "Error writing to socket. Status: %d", w_status);
        exit(1);
    }
    
    char status[4];
    while ((resp = read(sck, status, 4)) > 0) {}
    
    if (strcmp(status, MC_ACCEPT) == 0) {
        printf("ACCEPTED!\n");
    } else if (strcmp(status, MC_ACCEPT) == 0) {
        printf("FAILURE\n");
    } else {
        printf("DONT KNOW\n");
    }
    
    close(sck);
    

    问题是服务器在read()部分冻结了自己。它看起来像客户端发送文件名并等待服务器响应(具有状态)但服务器冻结在read()

    我以某种方式阻止TCP套接字?我的推理出了什么问题?

2 个答案:

答案 0 :(得分:1)

在服务器端:

char response[128];
int bytes_read;
while ((bytes_read = read(info.socket, response, 128)) > 0) {}

您尝试在多个read来电中阅读这128个字符。但它将永远阻塞,直到客户端关闭套接字(它连接TCP,除非对等关闭连接,否则总会有东西要读取)。

如果数据到达超过1个块,则代码不正确,因为第一个块将被下一个块覆盖,依此类推。您必须更改缓冲区的偏移量,并且不要每次都尝试读取128个字节,否则您将被卡住。

int bytes_read = 0;
while (bytes_read < 128)
{
  int currently_read = read(info.socket, response + currently_read, 128-bytes_read);
  bytes_read += currently_read;
}

在客户端,同样的问题也是如此:

你似乎在等待4个字符。

您尝试在第一个read中阅读这4个字符。但是你不能检查是否实际读取了4个字符(丢弃了返回代码)。

之后,您使用循环读取,直到获得0个字节。但由于连接没有结束,你就会被困在那里。

你想要的是在做其他事情之前准确读取4个字节。

增加缓冲区大小&amp; null-terminate你的字符串或strcmp将失败。

char status[5];
status[4] = '\0';
int nb_read = 0;
while (nb_read < 4)
{
  int currently_read = read(sck, status + nb_read, 4-nb_read);
  nb_read += currently_read;
}

答案 1 :(得分:0)

问题是您未在while循环内处理请求:

while ((bytes_read = read(info.socket, response, 128)) > 0) {}

这将保持循环,直到read()返回0,这在客户端关闭连接时发生,或者收到错误并返回-1。在它从客户端读取请求后,它会返回并再次调用read()。由于客户端没有发送任何其他内容,因此阻止。

这就是为什么杀死客户端会让它失败。这会关闭连接,因此它会获得EOF,read()会返回0

您需要处理循环内的输入:

while ((bytes_read = read(info.socket, response, sizeof response -1)) > 0) {
    response[bytes_read] = '\0'; // add string null terminator
    if (valid_request(files, files_count, response)) {
        write(info.socket, MC_ACCEPT, 4);
    } else {
        write(info.socket, MC_FAILURE, 4);
    }
}