2011-03-05 106 views
2

线程退出父进程时如何退出?当我运行服务器一切都很好。它坐在监听插座上。当客户端连接服务器线程来提供服务时。当他们来回交谈时,客户端退出,服务器也退出。我“米使用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); 
} 
+2

添加到您的服务器:检查一遍的行为:'信号(SIGPIPE, SIG_IGN);' – nos

+0

这解决了问题......如果你让这个答案而不是评论,我会很乐意接受它。 – KeatsKelleher

回答

6

您的服务器不断向客户端发送数据。 当您的客户端退出时,它没有读取要在套接字上读取的所有数据。

这种情况会产生一个TCP RST,当接收TCP RST时* nixes上的默认行为是将SIGPIPE信号传递给进程。 SIGPIPE信号的默认行为是退出程序。

对于TCP服务器,它通常忽略SIGPIPE信号,忽略SIGPIPE当提到的条件(客户端退出或关闭带有挂起数据的套接字)时,write()/ send()将返回一个错误,并将errno设置为EPIPE

在主加入这一()服务器的:

signal(SIGPIPE,SIG_IGN); 

一些更多的信息可以发现here

+0

。岩。谢谢。 – KeatsKelleher

3

exit终止该进程,以便包括所有线程你在相同的过程中产生,你应该从你的线程函数中返回而不需要调用exit。

+2

...或者调用'pthread_exit'来退出一个线程。 –

+0

我不知道pthreads,那么OP是否需要加入完成的线程来清理它们? –

+1

OP有2个不同的程序,他不是通过在线程中退出而终止。 – nos

2

exit()杀死了整个过程,它将杀死构成它的所有线程。你可以互换地使用“线程”和“过程”这两个词,这表明你脑子里可能会有一些混淆。

多个线程可以在单个进程中执行,但是如果进程死亡,则其所有线程都会死亡。

相关问题