一个IP地址和一个端口号可以一起唯一地标识一个进程ID吗

Can an IP address and a port number together uniquely identify a process ID?

本文关键字:一个 唯一 标识 进程 ID 一起 口号 地址 IP      更新时间:2023-10-16

一个IP地址和一个端口号能否一起唯一地标识一个进程ID?

我正在寻找一种方法来获得相应的进程ID,给定一个IP地址和端口号,但我不确定这样的IP/端口对是否可以唯一地标识一个pid。

不一定。如果一个套接字在进程中被打开/接受,然后分叉,那么子进程也打开了套接字,因此IP地址和端口号由两个进程使用。

正如Jonathan所指出的,这种关系不一定是唯一的。例如,有一些服务器实现(apache/prefork)使用子进程来并发处理请求。

但是,无论如何,您都可以使用特定的端口/地址获得进程列表(尽管单个端口/地址对可能有多个条目),也许在您的特定情况下,这是一个可行的解决方案:

例如,在Windows中,可以使用GetExtendedTcpTable函数,将TableClass参数设置为TCP_TABLE_OWNER_MODULE_*值之一。这将返回一个表,其中包含所有当前TCP端点的本地和远程地址/端口以及进程ID。

在Linux上肯定有类似的方法(尽管我不知道该怎么做…),因为这正是netstat -p程序所做的。

一次,只有一个进程可以绑定到给定的端口,因此给定一个端口,我们最多可以有一个进程侦听它。是的,多个进程可以通过同一端口发送和接收,但只有一个进程绑定到一个端口。

例如,在以下代码中,会出现"server:bind:Address Already in use"错误。然后,如果我们运行lsof-i:2100,那么在端口2100上只有一个进程id在侦听。

#define SERVERPORT "2100"
#define BUF_MAX 1024
#define BACKLOG 10
int data_connection(char* portno)
{
    struct addrinfo hints,*res,*clientinfo;
    int rv,datafd,yes=1,new_fd;
    char buf[BUF_MAX];
    struct sockaddr_storage their_addr;
    socklen_t addr_size;
    memset(&hints,0,sizeof(hints));
    hints.ai_family=AF_UNSPEC; 
    hints.ai_socktype=SOCK_STREAM;//connnection oriented.
    hints.ai_flags=AI_PASSIVE;
    if ((rv = getaddrinfo(NULL, portno, &hints, &res)) != 0) {
        fprintf(stderr, "getaddrinfo: %sn", gai_strerror(rv));
        return 1;
    }
    for(clientinfo=res;clientinfo!=NULL;clientinfo=clientinfo->ai_next)
    {
        if((datafd=socket(clientinfo->ai_family,clientinfo->ai_socktype,clientinfo->ai_protocol))==-1)
        {
            perror("server:datasocket");
            continue;
        }
        break;
    }
    if(setsockopt(datafd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int))==-1)
    {
        perror("setsockopt");
        exit(1);
    }
    if(bind(datafd,clientinfo->ai_addr,clientinfo->ai_addrlen)<0)
    {
        perror("server:bind");
        exit(1);
    }
    if(listen(datafd,BACKLOG)<0)
    {
        perror("server:listen");
        exit(1);
    }
    addr_size=sizeof(their_addr);
    if((new_fd=accept(datafd,(struct sockaddr*)&their_addr,&addr_size))<0)
    {
        perror("server:accept");
        exit(1);
    }
    close(datafd);
    datafd=new_fd;
    return datafd;
}
int main()
{
    int datafd;
    fork();
    datafd=data_connection(SERVERPORT);
}

在windows机器上,您可以获得侦听应用程序的进程ID。请参阅此问题。

添加特定于Windows的计数器示例:

Windows有一个http.sys(内核模式http协议侦听器)服务,它允许不同的应用程序共享端口。https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/net-tcp-port-sharing