Почему мой клиент убивает мой сервер? - PullRequest
2 голосов
/ 06 марта 2011

Как получается, что выход из родительского процесса также завершается?Когда я запускаю сервер, все хорошо.Он сидит и слушает на сокете.Когда клиент подключает серверные потоки для его обслуживания.Когда они разговаривают взад и вперед, клиент выходит, а сервер тоже выходит.Я использую pthread.h для потоков. Вот они!

Первый клиент:

#include <netinet/in.h>
#include <netdb.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>

#define CLIENT_CONNECTED 0
#define CLIENT_NOT_CONNECTED 1
#define PORT 9999
#define MAX_CLIENTS 100

using namespace std;

struct client {
    int socket;
    int state;
    pthread_t tid;
};

int 
connectToServer (char *address )
{
    struct hostent *hostinfo;
    struct sockaddr_in name;
    int s;  
    int rc = 0;

    if ( ( s = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
    {
        cerr<<"Client could not declare socket"<<"\n";
        exit( 1 );
    }

    name.sin_family = AF_INET;
    name.sin_port = htons ( ( unsigned short int ) PORT );
    name.sin_addr.s_addr = htonl( INADDR_ANY );
    hostinfo = gethostbyname ( address );

    if ( hostinfo == NULL )
    {
        cerr<<"Host unknown"<<"\n";
        exit( 1 );
    }   

    name.sin_addr = *( struct in_addr * ) hostinfo->h_addr;

    if ( connect( s, ( const sockaddr * ) &name, sizeof( name ) ) < 0 )
    {
        cerr<<"Could not connect to host"<<"\n";
        exit( 1 );
    }
    else 
    {
/*      if( fcntl( s, F_SETFL, O_NONBLOCK ) == -1 ) 
        {
            perror( "fcntl" );
            exit( 1 );
        } */

        char readbuf[1024];
        char message[ ] = "START";
        rc = send( s, message, strlen(message), 0 );
        cout<<"RC on send() was "<<rc<<"\n";
        if ( rc > 0 )
        {
            cout<<"using recv...\n";

            while( ( rc = recv( s, readbuf, 1, 0 ) ) > 0 )
            { 
                readbuf[ rc ] = '\0';
                cout<<"Server responds with: "<<readbuf<<"\n";
            }

            return true;
        }
        else 
        {
            return false;
        }
    }
}

void 
killsignal( int param )
{
   fprintf( stderr, "Disconnecting." );
   exit( 1 );
}

int 
main ( )
{
    signal( SIGKILL, killsignal );
    signal( SIGINT, killsignal );

    char address[] = "localhost";
    connectToServer( address );
}

И сервер:

#include <netinet/in.h>
#include <netdb.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>

#define CLIENT_CONNECTED 0
#define CLIENT_NOT_CONNECTED 1
#define PORT 9999
#define MAX_CLIENTS 100

using namespace std;

struct client {
    int socket;
    int state;
    pthread_t tid;
};

int 
sendClient( char *message, int *socket )
{
    int rc = 0;
    cout<<message<<"\n";
    rc = send( *socket, message, strlen(message), 0 ); 
    cout<<"send RC is: "<<rc<<"\n";
}

void 
strtochrstr( char **to, string from )
{

    int len = from.size( );

    *to = ( char * )malloc( ( len + 1 ) * sizeof( char ) );

    if ( to == NULL ){
        cout<<"out of memory!\n";
        exit( 1 );
    }

    *to[ 0 ] = '\0';

    strcpy( *to, from.c_str( ) );
}

int 
createSocket ( int *s )
{
    struct sockaddr_in name;

    if ( ( *s = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
    {
        cerr<<"Server: Socket"<<"\n";
    }

    name.sin_family = AF_INET;
    name.sin_port = htons( (unsigned short int) PORT );
    name.sin_addr.s_addr = htonl( INADDR_ANY );
    if ( bind( *s, ( struct sockaddr * ) &name, sizeof( name ) ) < 0 )
    {
        cerr<<"Could not bind to socket."<<"\n";
        exit( 1 );
    }

    return *s;
}

void *
serveClient( void *clientState )
{
    int c;
    int rc = 0;
    char readbuf[ 2 ];
    char message[ ] = "Message to client";//( char * ) malloc( 300 * sizeof( char ) );
    struct client *mystate = ( struct client * ) clientState;

    /* Set socket tot NONBLOCKING */
    if( fcntl( mystate->socket , F_SETFL, O_NONBLOCK ) == -1 ) 
    {
        perror( "fcntl" );
        exit( 1 );
    } 

    while ( true )
    {
        while ( ( rc = recv( mystate->socket, readbuf, 1 , 0 ) ) > 0 )
        {
            readbuf[ 1 ] = '\0'; 
            cout<<readbuf<<"\n";
        }
        sendClient( message, &( mystate->socket ) ); 
    }
}

int 
listenUp ( int *s )
{
    int i = 0;
    int error = 0;
    pthread_t clientIds[MAX_CLIENTS];
    struct client clients[MAX_CLIENTS];
    struct sockaddr_in fsaun[MAX_CLIENTS];  
    int fromlen[MAX_CLIENTS];   

    while ( i++ < MAX_CLIENTS )
        clients[i].state = CLIENT_NOT_CONNECTED;

    if ( listen( *s, 10 ) < 0 )
    {
        cerr<<"Could not listen on socket"<<"\n";
        exit( 1 );
    }   

    while ( true )
    {
        while ( ( clients[i++].state == CLIENT_CONNECTED && i < MAX_CLIENTS ) );    

        if ( ( clients[i].socket = accept( 
            *s, 
            ( sockaddr * ) &fsaun[i],
            ( socklen_t * ) &fromlen[i] ) ) < 0 )
        {
            cerr<<"Could not accept connection "<<i<<"\n";
        }
        else 
        {
            error = pthread_create(
                &clients[i].tid,
                NULL,
                serveClient,
                (void *)&clients[i]
            );
        }
        i = 0;
    }
}

void 
killsignal( int param )
{
   fprintf( stderr, "Disconnecting.\n" );
}

void 
intsignal( int param )
{
    fprintf( stderr, "Write error.\n" );
}

int 
main ( )
{
    signal( SIGKILL, killsignal );
    signal( SIGINT, intsignal );

    int mySock = createSocket( &mySock );
    listenUp( &mySock );
}

Ответы [ 3 ]

6 голосов
/ 06 марта 2011

Ваш сервер постоянно отправляет данные клиенту. Когда ваш клиент выходит, он не прочитал все данные, которые нужно прочитать на сокете.

Это условие будет генерировать TCP RST, поведение по умолчанию * nixes при получении TCP RST - это передача сигнала SIGPIPE процессу. Поведение по умолчанию сигнала SIGPIPE - выход из программы.

Для серверов TCP обычно просто игнорировать сигнал SIGPIPE, а игнорируемая SIGPIPE функция write () / send () вернет ошибку, когда упомянутое условие (клиент выйдет или закроет сокет с ожидающими данными) и установит для errno значение EPIPE

Добавьте это в main () вашего сервера:

signal(SIGPIPE,SIG_IGN);

Дополнительную информацию можно найти здесь

3 голосов
/ 06 марта 2011

exit завершает процесс, включая все потоки, созданные вами в этом же процессе.Вы должны просто вернуться из своих потоковых функций без вызова exit.

2 голосов
/ 06 марта 2011

exit() убивает весь процесс , который убивает все потоки, которые его составляют.Вы используете слова «поток» и «процесс» взаимозаменяемо, что предполагает, что между ними может быть некоторая путаница.

В одном процессе могут выполняться несколько потоков, но если процесс умирает, всеего нити умирают.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...