Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 套接字文件描述符在不同进程中是相同的_C++_Bash_Sockets - Fatal编程技术网

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

C++ 套接字文件描述符在不同进程中是相同的,c++,bash,sockets,C++,Bash,Sockets,我有一个简单的服务器客户端程序。当我通过同一C++程序中的一个循环建立所有客户端的连接时,每个客户端被分配一个不同的文件描述符,用于连接到服务器。但是,当我在单独的程序中建立连接时(例如,使用以下脚本),所有客户端都会获得相同的套接字fd: for i in {1..3} do ./client & done 第一种情况下的输出(在for循环中调用的客户端)是: 第二种情况下的输出(在单独的进程中调用)是: 这是我的密码: 客户端(版本1).cpp int main (int ar

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

for i in {1..3}
do
  ./client &
done
第一种情况下的输出(在for循环中调用的客户端)是:

第二种情况下的输出(在单独的进程中调用)是:

这是我的密码:

客户端(版本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;
}
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;
}
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);
}
Server.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;
}
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;
}
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);
}
intmain(intargc,char*argv[]){
int CLIENTS_CNT=3;
int server_sockfd;
字符温度;
int sockfd[客户];
服务地址中的结构sockaddr\u,返回地址;
socklen\u t len=sizeof(返回地址);
server\u sockfd=socket(AF\u INET,SOCK\u 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);
绑定(server_sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
监听(服务器、客户端);
对于(int c=0;c
下面是我的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;
}
int-sock\u-connect(std::string-servername,int-port){
int-sockfd,n;
服务地址中的结构sockaddr\u;
结构主机*服务器;
sockfd=套接字(AF_INET,SOCK_STREAM,0);
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(端口);
serv_addr.sin_addr.s_addr=inet_addr((char*)servername.c_str());
如果(connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))小于0号{
printf(“连接错误”);
返回-1;
}
返回sockfd;
}
int建立\u tcp\u连接(标准::字符串远程\u ip,int远程\u端口,int*sockfd){
*sockfd=sock_connect(远程_ip、远程_端口);
如果(*sockfd<0){
printf(“无法建立到服务器的TCP连接”);
返回-1;
}
返回0;
}

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

文件描述符通常是文件描述符表中的索引,由操作系统内核为每个进程创建。所以,它们的数字实际上是独立的,而你得到的数字3实际上是后面的第一个数字(0,1,2-stdin,stdout和stderr)


但是,套接字伪文件可能具有inode编号,这些编号在整个系统中是全局的。文件描述符是特定于某个进程的。在两个不同的进程中使用相同的编号引用两个不同的文件没有什么错。实际上,fd0始终是标准输入,标准输入可以针对不同的进程重定向


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

客户端和服务器的输出是什么?为什么您认为客户端应该获得不同的FD编号?@immibis我稍微改变了这个问题。关于这个问题,他们不应该吗?也许我错了,但我认为每次调用
socket
函数都应该返回一个唯一的文件描述符。我同意,它们是相同的。为什么这是出乎意料的?你为什么在乎?真正的问题是什么?因此,当两个单独的进程在具有相同套接字编号的套接字上写入/读取时,它们实际上是在向不同的端点写入/读取数据?@narengi并不完全如此。当您尝试读取fd=3的套接字时,调用
read(3,…)
,操作系统检查fd表中的第三个条目,发现它是一个套接字,并将您的请求传输到具有适当套接字实体(存储在fd表中)的网络堆栈。网络堆栈中发生的魔力有点复杂,但与公共文件处理层无关。@narengi,尝试调用
lsof-p
。我希望,这将提高你对fd的理解。这对你帮助很大。非常感谢。因此,为了总结(并验证我的理解没有错),OS维护了一个开放文件描述符表,其中每个描述符在其他进程的fd空间中不一定是唯一的(例如,多个进程的表中可能有条目fd=3),但它们的组合是唯一的。这似乎是对的吗?