2011-05-06 73 views
2

在每一个新的客户端连接分叉服务器进程C:“所有客户端连接的相同的文件描述符”(客户端服务器编程)

不同的进程(服务器即高管的其他孩子)不能识别客户端相同的FD用于分叉的孩子。

如何区分客户端在其他进程?

接受调用返回如果文件描述符新的sockfd

/* server process */ 
#include <ctype.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <signal.h> 
#define SIZE sizeof(struct sockaddr_in) 
void catcher(int sig); 
int newsockfd; 
int main(void) 
{ 
    int sockfd; 
    char c; 
    struct sockaddr_in server = {AF_INET, 7000, INADDR_ANY}; 
    static struct sigaction act; 
    act.sa_handler = catcher; 
    sigfillset(&(act.sa_mask)); 
    sigaction(SIGPIPE, &act, NULL); 
    /* set up the transport end point */ 
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
    { 
     perror("socket call failed"); 
     exit(1); 
    } 
    /* bind an address to the end point */ 
    if (bind(sockfd, (struct sockaddr *)&server, SIZE) == -1) 
    { 
     perror("bind call failed"); 
     exit(1); 
    } 
    /* start listening for incoming connections */ 
    if (listen(sockfd, 5) == -1) 
    { 
     perror("listen call failed"); 
     exit(1) ; 
    } 
    for (;;) 
    { 
     /* accept a connection */ 
     if ((newsockfd = accept(sockfd, NULL, NULL)) == -1) 
     { 
      perror("accept call failed"); 
      continue; 
     } 
     printf("New connection. File descriptor fd is %d\n",newsockfd); 
     /* spawn a child to deal with the connection */ 
     if (fork() == 0) 
     { 
      while (recv(newsockfd, &c, 1, 0) > 0) 
      { 
       c = toupper(c); 
       send(newsockfd, &c,1, 0); 
      } 
      /* when client is no longer sending information the socket can be closed and the child process terminated */ 
      close(newsockfd); 
      exit (0); 
     } 
     /* parent doesn't need the newsockfd */ 
     close(newsockfd); 
    } 
} 
void catcher(int sig) 
{ 
    close(newsockfd); 
    exit (0); 
} 












/* client process */ 
#include <ctype.h> 
#include <sys/types.h> 
#include<stdlib.h> 
#include<stdio.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#define SIZE sizeof(struct sockaddr_in) 
int main(void) 
{ 
    int sockfd; 
    char c, rc; 
    struct sockaddr_in server = {AF_INET, 7000}; 
    /* convert and store the server's IP address */ 
    server.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    /* set up the transport end point */ 
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
    { 
     perror("socket call failed"); 
     exit(1); 
    } 
    /* connect the socket to the server's address */ 
    if (connect (sockfd, (struct sockaddr *)&server, SIZE) == -1) 
    { 
     perror("connect call failed"); 
     exit(1); 
    } 
    /* send and receive information with the server */ 
    for(rc = '\n';;) 
    { 
     if (rc == '\n') 
      printf("Input a lower case character\n"); 
     c = getchar(); 
     send(sockfd, &c, 1, 0); 
     if (recv(sockfd, &rc, 1, 0) >0) 
      printf("%c", rc); 
     else 
     { 
      printf("server has died\n"); 
      close(sockfd); 
      exit(1); 
     } 
    } 
} 

回答

3

的文件描述符号是唯一只在它存在的过程中,并尽快,因为它是封闭的,它可以重复使用相同的值(例如下一次您拨打accept)。这不是“连接标识符”的好选择。

对于每个连接都有一个新进程的情况,连接最自然的标识符就是进程标识符 - 但是通过不保存返回值fork而抛弃了它。在父进程中,fork返回它创建的子进程的PID。你想保存并稍后使用它。尤其是,您可以使用它来杀死子进程或识别子进程何时退出(wait-系列函数会告诉您哪个子进程退出)。

当然如果你的整个模型是为每个连接使用一个单独的进程,我不知道为什么你需要在父进程中确定连接。如果每个连接都不是一个完全独立的进程,那么使用线程而不是进程可能会更好。

+0

我希望服务器进程的子3能够向该客户端发送消息。在这种情况下,PID无用。 主要代码在这里:https://github.com/smitpatel24/SChannel 我应该使用哪个IPC来实现这种机制(孩子3可以发送味精给客户端)? – smitrp 2011-05-08 06:35:17

相关问题