Can an IP address and a port number together uniquely identify a process ID?
I'm looking for a way to get the corresponding process ID, given an IP address and a port number, but I'm not sure whether such ip/port pairs can uniquely identify one pid.
Can an IP address and a port number together uniquely identify a process ID?
I'm looking for a way to get the corresponding process ID, given an IP address and a port number, but I'm not sure whether such ip/port pairs can uniquely identify one pid.
Not necessarily. If a socket is opened/accepted in a process, and it then forks, the child process also has the socket open, so the IP address and port number are used by two processes.
As Jonathan pointed out, the relation is not necessarily unique. For instance, there are server implementations (apache/prefork) which use child processes to handle requests concurrently.
But you can get the list of processes using a specific port/address anyway (although there might be multiple entries for a single port/address pair), perhaps in your specific case this is a viable solution:
In Windows, for example, you can use the GetExtendedTcpTable function, setting the TableClass parameter to one of the TCP_TABLE_OWNER_MODULE_* values. This returns a table containing local and remote address/port and process ID for all current TCP endpoints.
On Linux there are certainly similar ways (although I do not know by heart how to do it...), since this is exactly what the netstat -p program does.
At a time, only one process can bind to a given port, hence given a port we can have at most one process listening on it. Yes multiple processes can send & receive through the same port but only one process binds to a port.
e.g. in the following code one gets a "server:bind: Address Already in use" error. Then, if we run lsof -i:2100 we get only one process id listening on port 2100.
#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: %s\n", 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);
}
To add a Windows specific counter example:
Windows has a http.sys (the kernel-mode HTTP protocol listener) service which enables port sharing by different applications. https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/net-tcp-port-sharing
On a windows machine, you can obtain the process ID for a listening application. See this question.