我想在C中使用TCP套接字实现协议,这种方式有点像这样:
ACCEPT
或FAILURE
状态READY
状态到服务器服务器代码:
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套接字?我的推理出了什么问题?
答案 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);
}
}