套接字文件描述符在不同的进程中是相同的

时间:2015-02-22 22:56:16

标签: c++ bash sockets

我有一个简单的服务器 - 客户端程序。当我通过同一个c ++程序中的循环为所有客户端建立连接时,会为每个客户端分配一个与服务器连接的不同文件描述符。但是当我在单独的程序中建立连接时(例如使用以下脚本),所有客户端都获得相同的套接字fd:

for i in {1..3}
do
  ./client &
done

第一种情况下的输出(在for循环中调用客户端)是:

output on Server:
    For client 0 on sock 3
    For client 1 on sock 4
    For client 2 on sock 5
output on Client-version1: 
    Client connected to server on sock 4
    Client connected to server on sock 6
    Client connected to server on sock 7

和第二种情况下的输出(在不同的进程中调用)是:

output on Server:
    For client 0 on sock 3
    For client 1 on sock 4
    For client 2 on sock 5
output on Client 1-version2: 
    Client connected to server on sock 3
output on Client 2-version2:    
    Client connected to server on sock 3
output on Client 3-version2:    
    Client connected to server on sock 3

这是我的代码:

客户端(版本1).cpp

int main (int argc, char *argv[]) {
    int sockfd[3];
    std::string ip = "127.0.0.1";
    char temp_char;

    for (int i = 0; i < 3; i++) {
        establish_tcp_connection(ip.c_str(), 45678, &sockfd[i]);
        printf("Client connected to server on sock %d", sockfd[i]);
    }

    // make sure that the socket is not closed before other clients start
    // so, just send a dummy char back and forth
    for (int i = 0; i < 3; i++) 
        sock_sync_data (sockfd, 1, "W", &temp_char);    

    return 0;
}

客户端(版本2).cpp

int main (int argc, char *argv[]) {
    int sockfd;
    std::string ip = "127.0.0.1";
    char temp_char;

    establish_tcp_connection(ip.c_str(), 45678, &sockfd);
    printf("Client connected to server on sock %d", sockfd);

    // make sure that the socket is not closed before other clients start
    // so, just send a dummy char back and forth
    sock_sync_data (sockfd, 1, "W", &temp_char);    

    return 0;
}

Server.cpp

int main (int argc, char *argv[]) {
    int CLIENTS_CNT = 3;
    int server_sockfd;
    char temp_char;
    int sockfd[CLIENTS_CNT];

    struct sockaddr_in serv_addr, returned_addr;
    socklen_t len = sizeof(returned_addr);

    server_sockfd = socket (AF_INET, SOCK_STREAM, 0);

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(45678);

    bind(server_sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
    listen (server_sockfd, CLIENTS_CNT);

    for (int c = 0; c < CLIENTS_CNT; c++){
        sockfd[c] = accept (server_sockfd, (struct sockaddr *) &returned_addr, &len);
        printf("For client %d on sock %d", c, sockfd[c]);
    }

    for (int c = 0; c < CLIENTS_CNT; c++) {
        /* just send a dummy char back and forth */
        sock_sync_data (sockfd[c], 1, "W", &temp_char); 
    }

    close(server_sockfd);
}

这是我的 util 代码:

int sock_connect (std::string servername, int port) {
    int sockfd, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    serv_addr.sin_addr.s_addr = inet_addr((char*)servername.c_str());
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) LESS_THAN_SIGN 0){ 
        printf("ERROR connecting");
        return -1;
    }
    return sockfd;
}

int establish_tcp_connection(std::string remote_ip, int remote_port, int *sockfd) {
    *sockfd = sock_connect (remote_ip, remote_port);
    if (*sockfd < 0) {
        printf("failed to establish TCP connection to server ");
        return -1;
    }
    return 0;
}

3 个答案:

答案 0 :(得分:2)

文件描述符通常是文件描述符表中的索引,由每个进程的OS内核创建。所以,他们的数字实际上是独立的,你获得的数字3实际上是第一个数字(0,1,2-stdin,stdout和stderr)。

但是,套接字伪文件可能具有跨系统的全局的inode编号。他们很难达到。

答案 1 :(得分:2)

文件描述符特定于进程。在两个不同的进程中使用相同的数字指的是两个不同的文件没有错。实际上,FD 0始终是标准输入,标准输入可以重定向到不同的过程。

在第二种情况下,所有三个客户端都创建了不同的套接字,但它们都具有FD编号3(在该过程中)。

答案 2 :(得分:1)

这是完全正常的。套接字只是另一个文件描述符,所以它只是一个单一的...操作系统的网络堆栈处理你似乎认为应该成为FD的一部分的所有端点信息等。