gpt4 book ai didi

C : "same file descriptors of all client connections" (client server programming)

转载 作者:行者123 更新时间:2023-12-03 11:52:27 26 4
gpt4 key购买 nike

在每个新的客户端连接上 fork 服务器进程

不同的进程(服务器的其他子进程,即 exec)无法识别在 fork 子进程中使用相同 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);
}
}
}

最佳答案

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

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

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

关于C : "same file descriptors of all client connections" (client server programming),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5915144/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com