【问题标题】:Server program is stuck at send服务器程序卡在发送
【发布时间】:2012-03-04 03:20:53
【问题描述】:

我正在用 C 语言构建一个服务器客户端模型。客户端连接到服务器并开始交换数据。但是,用户可以在程序中随时结束客户端,但不会通知服务器。即使在客户端关闭后,服务器也会继续发送该数据。 我的印象是,如果服务器无法发送数据,发送函数将返回 -1,但我的服务器程序只是卡在发送

if((byteSent = send(new_fd, fileContents,  strlen(fileContents), 0)) == -1){ //

程序在上面一行停止。

我该如何克服这个问题?

//代码

   exitT = 0;
    //execution_count = 1;
    for(i=0;i<execution_count;i++)
    {  
        sleep(time_delay);

        //getting the current time on the server machine
        time_t t;
        time(&t);

        char *time=ctime(&t);
        printf("The Execution time at server =  %s\n",time);

        system(exec_command);

       /*Open the file, get file size, read the contents and close the file*/

        // Open the file
        fp = fopen(fileName,"r");

        // Get File Size
        fseek(fp,0,SEEK_END);
        dataLength = ftell(fp);
        rewind(fp);                

        fileContents = (char*)malloc(dataLength+1);
       // Read File
       fread(fileContents,1,dataLength,fp);
       fileContents[dataLength] = '\0';

        // Close file
         fclose(fp);    

       printf("sockfd = %d \n",new_fd);
       // send file length to client
       rc=send(new_fd, &dataLength,  sizeof(dataLength), 0) ;

       printf("length of client data = %d \n",rc);

        printf("sockfd = %d \n",new_fd);
       // send time to client
       rc=send(new_fd, time,  strlen(time), 0) ;

       printf("length of client time = %d \n",rc);

       usleep(20000);

       // Send file contents to Client
       while(dataLength>0){
            printf("sockfd = %d \n",new_fd);
            if((byteSent = send(new_fd, fileContents,  strlen(fileContents), 0)) == -1){
                printf("bytes sent = %d \n",byteSent);
                exitT = 1;
                break;
            }
            dataLength-=byteSent;
       }

       //Delete the log file 
       sprintf(deleteCommand,"rm %s",fileName);
       system(deleteCommand);
       if(exitT == 1)
           break;
     }

      bzero(fileName,sizeof(fileName));
      bzero(exec_command,sizeof(exec_command));
      bzero(deleteCommand,sizeof(deleteCommand));

      //decClientNum();
      kill(parent_id,SIGALRM);
      close(new_fd);  // parent doesn't need this
      printf("STATUS = CLOSED\n");

      exit(0);
  }   

谢谢

【问题讨论】:

    标签: c networking send


    【解决方案1】:

    我认为我参加聚会已经很晚了,但我认为这个答案可能会对某人有所帮助。

    如果发送套接字没有可用空间来保存要传输的消息,并且套接字文件描述符没有设置 O_NONBLOCK,则 send() 将阻塞,直到空间可用。

    当 send() 函数卡住时,可能会出现 TCP 窗口大小变为 0 的情况。这种情况发生在连接的另一端没有消费接收到的数据时。

    可能有这样的场景,接收端进程正在由 GDB 运行,并且发生了 segfault。

    1. TCP 连接保持建立。
    2. 数据正在连续发送。
    3. 接收端没有使用它。

    因此,接收器 TCP 窗口大小将不断减小,您可以发送数据,直到它大于零。一旦变为 0,send() 函数将永远卡住。

    由于问题中提到的情况不是关闭连接的情况。当一个进程在关闭的 TCP 连接上写一些东西时,它会收到一个信号 SIGPIPE。 SIGPIPE 的默认处理程序终止进程。因此,在关闭连接的情况下,如果您不使用自己的 SIGPIPE 处理程序,那么只要在套接字上写入内容,就应该通过默认处理程序终止进程。

    【讨论】:

      【解决方案2】:

      来自手册页:send() 中没有隐含交付失败的指示。本地检测到的错误由返回值 -1 指示。

      可能这样的事情可能会有所帮助:http://stefan.buettcher.org/cs/conn_closed.html

      【讨论】:

      • 该示例显示服务器正在从客户端接收某些内容,如果管道中没有任何内容,则认为客户端正在关闭。但是在我的程序中,当服务器向客户端发送数据时,客户端是关闭的。我的服务器程序在 send() 函数处停止。并且接收标志不适用于 send() 函数。
      【解决方案3】:

      我假设您正在为 Linux 或 Posix 系统编码。

      当像send 这样的系统调用失败时,它会返回 -1 并且设置errno;您很可能应该使用errno 找出失败的原因。

      您可以使用strace 找出您的服务器或其他服务器完成了哪些系统调用。当然,也可以使用gdb 调试器。

      您很可能需要多路复用输入或输出。执行此操作的系统调用是pollselect(以及相关的ppollpselect)。阅读例如select_tut(2) 手册页。

      您可能想要使用(或至少研究其源代码)现有的面向事件的库,例如 libeventlibev 等。(Gtk 和 Qt 框架也提供了自己的,甚至可以使用GUI 应用程序之外)。

      我强烈建议阅读有关advanced unix programmingunix network programing 的内容(也许还阅读有关advanced linux programming 的内容)。

      【讨论】:

      • 通常人们不能在家庭作业中使用这样的库。这将大大违背使用低级套接字函数和学习如何使用它们的目的。
      • 但他们至少可以研究他们的源代码,学到很多东西。
      • 确实——但对于一个简单的任务来说,它通常太复杂了。
      【解决方案4】:

      也许您正在使用 tcp 协议并且服务器正在等待 ACK。如果您希望连接是异步的,请尝试使用 udp。

      【讨论】:

      • 这是我网络任务的一部分,我必须使用 TCP
      猜你喜欢
      • 2014-10-18
      • 2012-07-24
      • 2020-03-03
      • 2015-08-24
      • 1970-01-01
      • 2013-06-05
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多