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

C:“;所有客户端连接的相同文件描述符“;(客户机-服务器编程),c,sockets,client-server,C,Sockets,Client Server,在每一个新的客户端连接上,分叉服务器进程 不同的进程(服务器的其他子进程,即exec)无法识别在分叉子进程中使用相同fd的客户端 如何在其他流程上区分客户端 如果文件描述符为new sockfd,则accept调用返回相同的值 /* server process */ #include <ctype.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h&g

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

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

如何在其他流程上区分客户端

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

/* 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); 
        } 
    } 
} 
/*服务器进程*/
#包括
#包括
#包括
#包括
#包括
#定义大小sizeof(结构sockaddr\u in)
空隙捕捉器(int sig);
int newsockfd;
内部主(空)
{ 
int-sockfd;
字符c;
服务器中的结构sockaddr_={AF_INET,7000,INADDR_ANY};
静态结构动作;
act.sa_handler=捕手;
sigfillset(&(act.sa_mask));
sigaction(SIGPIPE,&act,NULL);
/*设置传输端点*/
if((sockfd=socket(AF_INET,SOCK_STREAM,0))=-1)
{ 
perror(“套接字调用失败”);
出口(1);
} 
/*将地址绑定到端点*/
if(绑定(sockfd,(结构sockaddr*)和服务器,大小)=-1)
{ 
perror(“绑定调用失败”);
出口(1);
}
/*开始侦听传入连接*/
如果(监听(sockfd,5)=-1)
{ 
perror(“监听呼叫失败”);
出口(1);
} 
对于(;;)
{ 
/*接受连接*/
if((newsockfd=accept(sockfd,NULL,NULL))=-1)
{ 
perror(“接受呼叫失败”);
继续;
} 
printf(“新连接。文件描述符fd为%d\n”,newsockfd);
/*生成一个子项以处理连接*/
如果(fork()==0)
{ 
而(recv(newsockfd,&c,1,0)>0)
{ 
c=toupper(c);
发送(newsockfd和c,1,0);
} 
/*当客户端不再发送信息时,可以关闭套接字并终止子进程*/
关闭(newsockfd);
出口(0);
} 
/*父级不需要newsockfd*/
关闭(newsockfd);
} 
} 
空隙捕捉器(内部信号)
{ 
关闭(newsockfd);
出口(0);
}
/*客户端进程*/
#包括
#包括
#包括
#包括
#包括
#包括
#定义大小sizeof(结构sockaddr\u in)
内部主(空)
{ 
int-sockfd;
字符c,rc;
服务器中的结构sockaddr_={AF_INET,7000};
/*转换并存储服务器的IP地址*/
server.sin_addr.s_addr=inet_addr(“127.0.0.1”);
/*设置传输端点*/
if((sockfd=socket(AF_INET,SOCK_STREAM,0))=-1)
{ 
perror(“套接字调用失败”);
出口(1);
} 
/*将套接字连接到服务器的地址*/
if(连接(sockfd,(结构sockaddr*)和服务器,大小)=-1)
{ 
perror(“连接呼叫失败”);
出口(1);
} 
/*使用服务器发送和接收信息*/
对于(rc='\n';)
{ 
如果(rc=='\n')
printf(“输入小写字符\n”);
c=getchar();
发送(sockfd和c,1,0);
如果(recv(sockfd和rc,1,0)>0)
printf(“%c”,rc);
其他的
{
printf(“服务器已死亡\n”);
关闭(sockfd);
出口(1);
} 
} 
} 

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

在每个连接都有一个新进程的情况下,连接最自然的标识符是进程id——但由于没有保存
fork
的返回值,您已经将它丢弃了。在父进程中,
fork
返回它创建的子进程的pid。您希望保存此文件并在以后使用。特别是,您可以使用它来终止子进程或识别子进程何时退出(
wait
-家族函数将告诉您哪个子进程退出)


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

我希望服务器进程的子进程3能够向该客户端发送消息。在这种情况下,PID没有用处。主要代码如下:我应该使用哪个IPC来实现这个机制(子3可以向客户端发送消息)?