【问题标题】:C : "same file descriptors of all client connections" (client server programming)C:“所有客户端连接的相同文件描述符”(客户端服务器编程)
【发布时间】:2011-08-20 09:14:02
【问题描述】:

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

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

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

如果文件描述符为 new 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); 
        } 
    } 
} 

【问题讨论】:

    标签: c sockets client-server


    【解决方案1】:

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

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

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

    【讨论】:

    • 我希望服务器进程的子 3 能够向该客户端发送消息。PID 在这种情况下没有用。主要代码在这里:github.com/smitpatel24/SChannel我应该使用哪个IPC来实现这个机制(孩子3可以向客户端发送消息)?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-06
    • 2016-02-16
    • 2012-05-22
    • 2019-03-17
    • 2013-05-18
    • 1970-01-01
    • 2023-04-09
    相关资源
    最近更新 更多