C:"所有客户端连接&QUOT的同一文件描述符; (客户端服务器编程) [英] C : "same file descriptors of all client connections" (client server programming)

查看:192
本文介绍了C:"所有客户端连接&QUOT的同一文件描述符; (客户端服务器编程)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

在派生的子用不同的工艺(即服务器的EXEC其他孩子)不能识别客户端相同的FD。

我如何能够区分客户端上的其他进程??

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

  / *服务器进程* /
#包括LT&;&文件ctype.h GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / socket.h中>
#包括LT&; netinet / in.h中>
#包括LT&;&signal.h中GT;
#定义尺寸的sizeof(结构SOCKADDR_IN)
无效捕手(INT SIG);
INT newsockfd;
INT主要(无效)
{
    INT的sockfd;
    焦炭℃;
    结构SOCKADDR_IN服务器= {AF_INET,7000,INADDR_ANY};
    静态结构sigaction的行为;
    act.sa_handler =捕手;
    sigfillset(及(act.sa_mask));
    的sigaction(SIGPIPE,&安培;行为,NULL);
    / *建立运输终点* /
    如果((的sockfd =插座(AF_INET,SOCK_STREAM,0))== -1)
    {
        PERROR(插座调用失败);
        出口(1);
    }
    / *的地址绑定到结束点* /
    如果(绑定(的sockfd,(结构sockaddr *)及服务器,SIZE)== -1)
    {
        PERROR(绑定调用失败);
        出口(1);
    }
    / *开始监听传入的连接* /
    如果(听(的sockfd,5)== -1)
    {
        PERROR(听调用失败);
        出口(1);
    }
    为(;;)
    {
        / *接受连接* /
        如果((newsockfd =接受(的sockfd,NULL,NULL))== -1)
        {
            PERROR(接受调用失败);
            继续;
        }
        的printf(新建连接文件描述符fd为%d \\ n,newsockfd);
        / *生成一个子来处理连接* /
        如果(叉()== 0)
        {
            而(的recv(newsockfd,和C,1,0)&0)
            {
                C = TOUPPER(C);
                发送(newsockfd,和C,1,0);
            }
            / *当客户不再发送信息的插座可以被关闭和终止子进程* /
            关闭(newsockfd);
            出口(0);
        }
        / *母体不需要newsockfd * /
        关闭(newsockfd);
    }
}
无效捕手(INT SIG)
{
    关闭(newsockfd);
    出口(0);
}
/ *客户端进程* /
#包括LT&;&文件ctype.h GT;
#包括LT&; SYS / types.h中>
#包括LT&;&stdlib.h中GT;
#包括LT&;&stdio.h中GT;
#包括LT&; SYS / socket.h中>
#包括LT&; netinet / in.h中>
#定义尺寸的sizeof(结构SOCKADDR_IN)
INT主要(无效)
{
    INT的sockfd;
    焦C,RC;
    结构SOCKADDR_IN服务器= {AF_INET,7000};
    / *转换和存储服务器的IP地址* /
    server.sin_addr.s_addr = inet_addr(127.0.0.1);
    / *建立运输终点* /
    如果((的sockfd =插座(AF_INET,SOCK_STREAM,0))== -1)
    {
        PERROR(插座调用失败);
        出口(1);
    }
    / *套接字连接到服务器的地址* /
    如果(连接(的sockfd,(结构sockaddr *)及服务器,SIZE)== -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);
        }
    }
}


解决方案

文件描述符数只在它存在的过程中是独一无二的,只要它是封闭的,它可以重复使用(例如下次呼叫时间接受)。这不是连接标识符。

的一个不错的选择

在你的情况,你有一个新的进程为每个连接,用于连接的最自然的标识符将是进程ID - 但你通过不保存的返回值抛出叉它扔掉。在父进程,返回它创建的子进程的PID。要保存这个以后使用它。特别是,你可以用它来杀死子进程或识别时,子进程退出( - 家庭功能会告诉你哪个孩子退出)。

当然,如果你的整个模型是使用一个单独的进程为每个连接,我不知道为什么你需要找出所有在父进程的连接。如果每个连接不是完全独立的过程中,你可能做了很多更好的使用,而不是进程中的线程。

On every new client connection forked server process

different processes(other children of server i.e. exec) couldn't identify that client with same fd in used in forked child.

How can I differentiate client on other processes ??

accept call is returning same value if file descriptor 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); 
        } 
    } 
} 

解决方案

The file descriptor number is unique only within the process it exists in, and as soon as it's closed, it can be reused (for example the next time you call accept). It is not a good choice of "connection identifier".

In your case where you have a new process for each connection, the most natural identifier for a connection would be the process id - but you've thrown it away by not saving the return value of fork. In the parent process, fork returns the pid of the child process it created. You want to save this and use it later. In particular you can use it to kill the child process or identify when the child process exits (wait-family functions will tell you which child exited).

Of course if your whole model is to use a separate process for each connection, I'm not sure why you need to identify connections at all in the parent process. If each connection is not a completely independent process, you might do a lot better using threads instead of processes.

这篇关于C:&QUOT;所有客户端连接&QUOT的同一文件描述符; (客户端服务器编程)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆