2011-12-04 105 views
2

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

#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; 
} 
+1

大家都知道,系统调用总是成功.. –

+2

_What我做错了?_不检查返回值。 – ninjalj

+0

@ninjalj我省略了它们以使代码简短 –

回答

1

我的第一个想法是,你从来没有真正关闭与套接字的连接。在你的线程内,你有一个无限循环,里面没有任何东西可以打破它。

试着这么做

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

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

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

5

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

要忽略:

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

要处理,你需要定义和规定的信号处理函数。

+0

这是正确的答案。但是,如果你这样做,你需要处理来自'send()'的错误,因为写入一个封闭的套接字将返回一个'EPIPE'错误。这是除了处理'read()'中的一个返回值外,就像被接受的答案一样。 –