Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.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
TCP连接出现错误和意外行为_C_Tcp - Fatal编程技术网

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

我希望我的TCP服务器和客户端能够根据对方说的话相互“交谈”。但当我运行时,它似乎经历了一次迭代,但服务器和客户端似乎都“挂起”在那里。一旦我在客户端杀死它,我最终会得到一个断管错误

有人能解释我做错了什么吗

服务器代码段:

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);