C:“所有客户端连接的相同文件描述符”(客户端服务器编程)

在每个新客户端连接分叉服务器进程

不同的进程(服务器的其他子进程,即exec)无法识别在分叉子进程中使用相同fd的客户端。

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

如果文件描述符是新的sockfd,则accept调用返回相同的值

/* server process */ #include  #include  #include  #include  #include  #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  #include  #include #include #include  #include  #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); } } } 

文件描述符号仅在其存在的过程中是唯一的,并且一旦关闭,它就可以被重用(例如,下次调用accept )。 它不是“连接标识符”的好选择。

在您为每个连接创建一个新进程的情况下,连接的最自然标识符将是进程ID – 但是您通过不保存fork的返回值将其抛弃。 在父进程中, fork返回它创建的子进程的pid。 您想保存它并在以后使用它。 特别是,您可以使用它来终止子进程或识别子进程何时退出( wait家庭function将告诉您哪个子进程退出)。

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