Linux с многопоточным сервером C - PullRequest
2 голосов
/ 04 декабря 2011

Я написал этот сервер на основе онлайн-учебника. Моя цель - создать новую ветку для каждого нового клиентского соединения. Эта часть работает нормально, но проблема в том, что серверная программа завершает работу всякий раз, когда один из клиентов отключается. Что я делаю не так?

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

Ответы [ 3 ]

5 голосов
/ 04 декабря 2011

Если вы попытаетесь send() к закрытой розетке, сигнал SIGPIPE будет повышен.Если вы не проигнорируете или не обработаете этот сигнал, он завершит процесс.

Чтобы игнорировать:

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

Для обработки необходимо определить и указать функцию обработчика сигнала.

3 голосов
/ 04 декабря 2011

Ваша подпрограмма SocketHandler не обрабатывает условия конца файла. recv (или read ) в этом случае дает 0.

И вам, вероятно, следует использовать системный вызов shutdown для отключения соединения.

1 голос
/ 04 декабря 2011

Моя первая мысль: на самом деле вы никогда не закрываете соединение с сокетом. Внутри вашей нити у вас есть бесконечный цикл, и внутри ничего нет, чтобы разорвать его.

Попробуйте что-то вроде

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...