【问题标题】:Linux threaded C serverLinux 线程化 C 服务器
【发布时间】:2011-12-04 12:19:22
【问题描述】:

我根据在线教程编写了这个服务器。 我的目标是为每个新的客户端连接创建一个新线程。这部分工作正常,但问题是只要其中一个客户端断开连接,服务器程序就会退出。 我做错了什么?

#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <netinet/in.h>
#include <resolv.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>

void* SocketHandler(void*);

int main(int argv, char** argc){
    int host_port= 1101;
    struct sockaddr_in my_addr;
    int hsock;
    int * p_int ;
    int err;
    socklen_t addr_size = 0;
    int* cs;
    struct sockaddr_in sadr;
    pthread_t thread_id=0;

    hsock = socket(AF_INET, SOCK_STREAM, 0);
    p_int = (int*)malloc(sizeof(int));
    *p_int = 1;

    setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int));
    setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int));
    free(p_int);

    my_addr.sin_family = AF_INET ;
    my_addr.sin_port = htons(host_port);
    memset(&(my_addr.sin_zero), 0, 8);
    my_addr.sin_addr.s_addr = INADDR_ANY ;

    bind( hsock, (struct sockaddr *)&my_addr, sizeof(my_addr));
    listen( hsock, 10);
    addr_size = sizeof( struct sockaddr_in);

while(1){
    printf("waiting for a connection\n");
        cs = (int*)malloc(sizeof(int));
    if((*cs = accept( hsock, (struct sockaddr*)&sadr, &addr_size))!= -1){
        pthread_create(&thread_id,0,&SocketHandler, (void*)cs );
        pthread_detach(thread_id);
    }
    else{
        fprintf(stderr, "Error accepting %d\n", errno);
    }
    }
}

void* SocketHandler(void* lp){
    int *csock = (int*)lp;
    char buffer[1024];
    int buffer_len = 1024;
    int bytecount;
    while (1){
    memset(buffer, 0, buffer_len);
        bytecount = recv(*csock, buffer, buffer_len, 0);
    printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer);

    strcat(buffer, " SERVER ECHO");
    bytecount = send(*csock, buffer, strlen(buffer), 0);    
    printf("Sent bytes %d\n", bytecount);
    }
    free(csock);
    return NULL;
}

【问题讨论】:

  • 众所周知,系统调用总是成功的..
  • 我做错了什么?没有检查返回值。
  • @ninjalj 我省略了他们以使代码简短
  • Malloc() 处理一个 int 大小的对象(而不是释放它)不会为你赢得诺贝尔奖。
  • 如果您想节省空间,请将错误处理代码替换为注释 /* handle any error here */ 这样您就可以节省空间并且不会让人认为这是问题所在。

标签: c linux multithreading sockets


【解决方案1】:

如果您尝试将send() 连接到已关闭的套接字,则会引发信号SIGPIPE。如果您不忽略或处理此信号,它将终止该过程。

忽略:

sigset(SIGPIPE, SIG_IGN); /* check return value to ensure success. */

要处理你需要定义和指定一个信号处理函数。

【讨论】:

  • 这是正确的答案。但是,如果这样做,您需要处理来自send() 的错误,因为写入关闭的套接字将返回EPIPE 错误。这是处理来自read() 的零返回值的补充,如已接受的答案。
【解决方案2】:

您的SocketHandler 例程不处理文件结束条件。在这种情况下,recv(或read)给出 0。

您可能应该使用shutdown 系统调用来关闭连接。

【讨论】:

    【解决方案3】:

    我的第一个想法是你永远不会真正关闭到套接字的连接。在您的线程内部,您有一个无限循环,内部没有任何东西可以破坏它。

    试试类似的东西

    while ((bytecount = recv(*csock, buffer, buffer_len, 0)) > 0) {
       printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer);
       strcat(buffer, " SERVER ECHO");
       bytecount = send(*csock, buffer, strlen(buffer), 0);
       printf("Sent bytes %d\n", bytecount);
       memset(buffer, 0, buffer_len);
    }
    // bytecount should be <0 for an error or == 0 for EOF received from sender
    
    shutdown(csock, SHUT_WR);
    close(*csock)
    

    【讨论】:

      猜你喜欢
      • 2015-04-11
      • 2020-10-04
      • 2015-08-11
      • 2011-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-22
      • 2012-06-15
      相关资源
      最近更新 更多