多个本地进程具有相同的套接字

Multiple local processes have the same socket

我有点 socket/net 代码新手,所以这可能是一个愚蠢的问题。

我正在使用 AF_INET 协议运行多个本地 "clients" 和一个本地 "server"。

但是,当我尝试将所有客户端连接到服务器时,它们似乎都在同一个套接字上进行连接,这使得从一个单一的读取变得毫无意义。

下面的代码演示了这个问题,独立于任何服务器代码。

#include <iostream>
#include <sys/socket.h>

int main(int argc, char* argv[])
{
    int sockfd;     // socket file descriptor

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    std::cout<<"socket is "<<sockfd<<std::endl;

    /* perform various i/o tasks */

    return 0;
}

这里的套接字总是3,不管这些进程中有多少正在运行。

这是预期的吗?如果是这样,那么处理这类事情的最佳方法可能是什么,因为我想使用互联网协议在我的本地网络或在线上允许相同的功能。

是的,这是意料之中的; file descriptors — 至少,POSIX 兼容的 — 由您的 OS 在每个进程的基础上分发:

Generally, a file descriptor is an index for an entry in a kernel-resident array data structure containing the details of open files. In POSIX this data structure is called a file descriptor table, and each process has its own file descriptor table. The process passes the file descriptor to the kernel through a system call, and the kernel will access the file on behalf of the process. The process itself cannot read or write the file descriptor table directly.

On Linux, the set of file descriptors open in a process can be accessed under the path /proc/PID/fd/, where PID is the process identifier.

In Unix-like systems, file descriptors can refer to any Unix file type named in a file system. As well as regular files, this includes directories, block and character devices (also called "special files"), Unix domain sockets, and named pipes. File descriptors can also refer to other objects that do not normally exist in the file system, such as anonymous pipes and network sockets.

因此,在您的情况下,很可能已经默认分配了以下内容:

  • 0 标准输入
  • 1 标准输出
  • 2 标准错误

所以第一个要求自己变成3

这个你完全不用担心。进程 1100 上的 FD 3 与进程 1101 上的 FD 3 完全不同。这不会对您的代码或 client/server 系统造成问题。您可能刚刚通过测试就发现了这一点。

socket 返回的号码 不是 套接字号,它只是 OS 维护的 table 的不透明索引and/or 语言运行时。每个进程都会有自己的table,所以这些数字重复是正常的,不用担心。

您可以使用 getsockname 获取有关套接字本身的扩展信息,例如端口号。