服务器程序卡在发送处

发布于 2025-01-05 03:11:22 字数 2373 浏览 5 评论 0 原文

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

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

谢谢

I am building a server client model in C. The clients connects to the server and they start exchanging data. However, the user can end the client at any time in the program, but the server is not notified about it. The server keeps sending that data even after the client is closed.
I was in the impression that send function will return -1 if the server is unable to send the data, but my server program just stuck at send

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

the program just halts at the above line.

How do I overcome this problem?

//Code

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

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

挽心 2025-01-12 03:11:22

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

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

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

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

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

我强烈建议阅读高级unix编程unix 网络编程(也许还涉及高级 Linux 编程)。

I assume you are coding for a Linux or Posix system.

When a syscall like send fails it returns -1 and sets the errno; you very probably should use errno to find out why it failed.

You could use strace to find out which syscalls are done by your sever, or some other one. Of course, use also the gdb debugger.

You very probably need to multiplex inputs or outputs. The system calls doing that are poll, select (and related ppoll and pselect). Read e.g. the select_tut(2) man page.

You may want to use (or at least to study the source code of) existing event oriented libraries like libevent, libev etc.. (Both Gtk and Qt frameworks provide also their own, which might be used even outside of GUI applications).

I strongly suggest reading about advanced unix programming and unix network programing (and perhaps also about advanced linux programming).

瞎闹 2025-01-12 03:11:22

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

maybe you're using a tcp protocol and the server is waiting for an ACK. Try using udp if you want your connection to be asynchronous.

微凉 2025-01-12 03:11:22

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

可能这样的东西可能会有所帮助: http://stefan.buettcher.org/cs/conn_lined.html< /a>

From the man page: No indication of failure to deliver is implicit in a send(). Locally detected errors are indicated by a return value of -1.

Proably something like this might help: http://stefan.buettcher.org/cs/conn_closed.html

無心 2025-01-12 03:11:22

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

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

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

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

  1. TCP 连接保持已建立状态。
  2. 数据正在连续发送。
  3. 接收端不消耗它。

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

由于问题中提到的情况不是关闭连接的场景。当进程在关闭的 TCP 连接上写入内容时,它会收到信号 SIGPIPE。 SIGPIPE 的默认处理程序终止进程。因此,在关闭连接的情况下,如果您不使用自己的 SIGPIPE 处理程序,则每当在套接字上写入内容时,默认处理程序都应终止进程。

I think I am pretty late in the party, but I think this answer might help someone.

If space is not available at the sending socket to hold the message to be transmitted, and the socket file descriptor does not have O_NONBLOCK set, send() shall block until space is available.

When send() function gets stuck, there might be a situation like, TCP window size has become 0. It happens when the other end of the connection is not consuming received data.

There might be a scenario like this, the receiving end process is running by GDB and segfault occurred.

  1. The TCP connection remains established.
  2. Data is being send continuously.
  3. The receiver end is not consuming it.

Consequently the receiver TCP window size will keep decreasing and you can send data till it is greater than zero. Once it becomes 0, send() function will get stuck forever.

As the situation mentioned in the question is not a scenario of closed connection. When a process writes something on a closed TCP connection, it receives a signal SIGPIPE. Default handler of SIGPIPE terminates the process. So, in a closed connection scenario if you are not using your own SIGPIPE handler then process should be terminated by default handler whenever something is written on the socket.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文