我如何在C中find一个端口可以自由使用?

操作系统是Linux。 我有一个服务器进程,可以实时更改其端口。 但是,我想提前知道如果一个端口是绑定之前是免费的。

scheme:服务器绑定localhost:5000,并接收绑定在localhost:6000的请求。 服务器必须检查端口是否空闲。 这个问题寻求的答案,提供了一个例程,检查一个端口是否免费。

为了logging,我编辑我的问题与代码片断,检查端口是否可以使用。 这并不意味着它会被使用。 下面的代码回答“如果端口现在可用”的问题,它不使用它。 打开一个套接字,检查绑定是否返回EADDRINUSE并closures套接字。

#include <iostream> #include <sys/socket.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <errno.h> int main(int argc, char **argv) { struct sockaddr_in serv_addr; if( argc < 2 ) return 0; int port = atoi(argv[1]); int sockfd = socket(AF_INET, SOCK_STREAM, 0); if( sockfd < 0 ) { printf("socket error\n"); return 0; } else { printf("Opened fd %d\n", sockfd); } bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(port); if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { if( errno == EADDRINUSE ) { printf("the port is not available. already to other process\n"); } else { printf("could not bind to process (%d) %s\n", errno, strerror(errno)); } } if (close (sockfd) < 0 ) { printf("did not close fd: %s\n", strerror(errno)); return errno; } return 0; } 

以下是一些示例运行(部分输出)

 [bash{1051}{51}]:[~/some_sources/checkbind]::./a.out 41067 the port is not available. already to other process [bash{1052}{52}]:[~/some_sources/checkbind]::./a.out 22 could not bind to process (13) Permission denied [bash{1053}{53}]:[~/some_sources/checkbind]::./a.out 22000 Opened fd 3 

Solutions Collecting From Web of "我如何在C中find一个端口可以自由使用?"

这是一个明显的竞争条件 ,因为系统上的其他进程可能并行绑定到端口。 所以,你找到的任何解决方案都是不完美的,你仍然需要按照“尝试bind() ,如果失败,选择一个新的端口号再试一次”方法。

如果你的服务器被告知要使用什么端口,只需bind()它。 认真。

当然,你可以解析/proc/net/tcp并查看端口是否在使用中。 但是呢? 你现在仍然需要调用bind() ,你知道你的端口是免费的,它会告诉你端口是否空闲,所以在/proc/net/tcp中徘徊没有任何意义。 (慢!)字符串生成和解析以及额外的内核访问,通过不太好的优化(读取:与bind()相比超级慢)的诊断路径,只是为了在解析完成之前获得可能已经过时的信息它。 所以只需调用bind()并快乐。

我自己努力,并稍微修改了你的代码。

解决办法是设置serv_addr.sin_port = 0 (自动分配端口)。

注意bind()getsockname()行中有从sockaddr_insockaddr不洁行为。 我已经看到它做了很多地方,我正在寻找一个更安全的解决方案。

 #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> // ... snip ... int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock < 0) { printf("socket error\n"); return; } printf("Opened %d\n", sock); struct sockaddr_in serv_addr; bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = 0; if (bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { if(errno == EADDRINUSE) { printf("the port is not available. already to other process\n"); return; } else { printf("could not bind to process (%d) %s\n", errno, strerror(errno)); return; } } socklen_t len = sizeof(serv_addr); if (getsockname(sock, (struct sockaddr *)&serv_addr, &len) == -1) { perror("getsockname"); return; } printf("port number %d\n", ntohs(serv_addr.sin_port)); if (close (sock) < 0 ) { printf("did not close: %s\n", strerror(errno)); return; } 

节目输出

 Opened 4 port number 59081