TCP连接出现错误和意外行为
我希望我的TCP服务器和客户端能够根据对方说的话相互“交谈”。但当我运行时,它似乎经历了一次迭代,但服务器和客户端似乎都“挂起”在那里。一旦我在客户端杀死它,我最终会得到一个断管错误 有人能解释我做错了什么吗 服务器代码段:TCP连接出现错误和意外行为,c,tcp,C,Tcp,我希望我的TCP服务器和客户端能够根据对方说的话相互“交谈”。但当我运行时,它似乎经历了一次迭代,但服务器和客户端似乎都“挂起”在那里。一旦我在客户端杀死它,我最终会得到一个断管错误 有人能解释我做错了什么吗 服务器代码段: while(feof(file_ptr) == 0) { fscanf(file_ptr, "%s", supplies); printf("%s\n", supplies); //SEND supplies to all clients (cur
while(feof(file_ptr) == 0)
{
fscanf(file_ptr, "%s", supplies);
printf("%s\n", supplies);
//SEND supplies to all clients (currently just one client)
n = write(newsockfd, supplies, strlen(supplies));
if (n < 0)
{
error("ERROR writing to socket");
}
//Receive a request from client that they can use supply
bzero(buffer,2);
n = read(newsockfd,buffer,2);
if (n < 0)
{
error("ERROR reading from socket");
}
printf("Who is using supply? %s\n", buffer);
if(strcmp(buffer, "A"))
{
aRounds++;
}
while(done != 1)
{
//WAIT loop until message CO is received from client
bzero(buffer,2);
n = read(newsockfd,buffer,2);
if (n < 0)
{
error("ERROR reading from socket");
}
printf("Done? %s\n", buffer);
if(strcmp(buffer, "CO"))
{
done = 1;
}
}
done = 0;
}
fclose(file_ptr);
n = write(newsockfd, "DN", 2);
while(noSupplies != 1)
{
//RECEIVE MSG from server about supplies
bzero(buffer,2);
n = read(sockfd,buffer,2);
if (n < 0)
{
error("ERROR reading from socket");
}
printf("%s\n",buffer);
if(strcmp(buffer, "BC") == 0 || strcmp(buffer, "CB") == 0)
{
//SEND server msg that you are using supply
n = write(sockfd,"A", 1);
if (n < 0)
{
error("ERROR writing to socket");
}
printf("Client A has received components %s during round %d.\n", buffer, round);
n = write(sockfd,"CO", 2);
if (n < 0)
{
error("ERROR writing to socket");
}
}
else if(strcmp(buffer, "DN"))
{
noSupplies = 1;
}
round++;
}
以及以下来自客户的信息(杀戮前):
然后在杀了客户之后。。我从服务器获得以下信息:
BC
Who is using supply? A
Done? CO
Done?
CB
Who is using supply?
Done?
CB
Who is using supply?
Done?
BC
Broken pipe
有人知道我做错了什么吗?(正在寻找代码修复!)
仅供参考。。我最终将更改服务器代码,以处理侦听多个客户端(TCP)的问题,但每次只会遇到一个障碍,对吗
谢谢 不确定这是否是你的全部问题,但是
bzero(buffer, 2);
n = read(socket, buffer, 2);
是不正确的,因为如果读取确实得到了2个字节,并且它们都不是0,那么缓冲区可能不是以null结尾的字符串(除非之前有什么东西这样做)
对strcmp的多次调用也应该总是因为同样的原因失败——读入字符串不是以0结尾的,因此strcmp认为它会继续进行,因此与比较字符串不同,即使第一个字母相同
编辑
n=读取(套接字、缓冲区、2);
如果(n您的服务器代码在开始时只向客户机写入一次内容,然后在循环中—它只是读取
OTOH您的客户机在循环中读写
由于您在阻塞模式下使用套接字,这意味着您的客户端最终将在调用recv
时被阻塞
附言。
没有冒犯-但是你有很多东西要学
TCP是一个隧道。当您的服务器在一次调用中向send
/write
发送2字节数据时,无法保证您的客户端将在一次调用recv
中读取此数据
因此,读取和解析总是必须在某种循环中完成
您无法编写一个真正健壮的客户机/服务器,它只能使用阻塞I/O来按需超时/中断
学,学,学
那么你是说缓冲区必须是一个空终止字符串?如果你想把它当作一个C字符串,就像printf
和strcmp
那样,那么是的,你需要确保你读入的最后一个字符后面的字符被设置为0。我不确定这是否能解决你的问题,因为我真的不知道我很清楚它应该做什么。好的,所以我把所有我正在写的案例都改成了结尾处有\n,并增加了发送的大小1。并且把所有的读取大小都增加了1。例如,n=write(sockfd,“CO\n”,3);bzero(buffer,3);n=read(socket,buffer,3);改变它似乎解决了我的问题!!:)所有的改变都是必要的还是仅仅在阅读上。。正在添加缓冲区[n]=0;没有任何帮助,但一旦我改变了一切,在字符串停止“挂起”并按预期完成程序后发送一行新行……我不明白为什么这会改变任何事情(特别是在TCP方面,尽管可能是在标准输出打印方面),但我很高兴它现在适合您。您应该阅读valdo在其回答中所说的关于一次读取/接收呼叫中没有数据的内容。依靠这一点,程序有时会工作,有时会失败,这似乎不是什么好理由。谢谢你的评论!我在学习!因此,这是一个实践计划!实际上,我在每次写东西时都会输入/n个字符来修复它:Doh和yes,它应该在开始时只写一次,然后只听两个响应以继续:)好吧,我的意思是,当你使用阻塞I/O时,你实际上失去了对程序流的控制。你变得依赖同伴了。除非它向你发送任何信息-你被阻止了。因此,我明白了,最好异步使用套接字。。由于文本文件中的内容,它总是会发送一些东西。一旦我添加了新的客户端和不同的文本文件,总会有人回复。。因此,对于我的下一个示例,我将接受您的建议并异步尝试:)是的,可以使用阻塞I/O编写一个具有中断和超时能力的健壮客户机/服务器。只需使用select()。
BC
Who is using supply? A
Done? CO
Done?
CB
Who is using supply?
Done?
CB
Who is using supply?
Done?
BC
Broken pipe
bzero(buffer, 2);
n = read(socket, buffer, 2);
printf("%s", buffer);
n = read(socket, buffer, 2);
if (n<0) {
die_horrible_death();
}
buffer[n] = 0; // since arrays are 0 indexed this should be after last read character
printf("I just read: \"%s\"\n", buffer);