- 论坛徽章:
- 0
|
本帖最后由 redcoder 于 2016-01-28 11:17 编辑
现在有个需求是列出系统上所有进程使用的tcp连接上,哪些端口可以被复用,以及哪些端口正在被复用?
我的思路是用netstat -anpt 列出所有tcp连接:
[root@localhost 桌面]# netstat -anpt
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1994/rpcbind
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 2212/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 2101/cupsd
tcp 0 0 127.0.0.1:28888 0.0.0.0:* LISTEN 3459/./test2
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2382/master
tcp 0 0 0.0.0.0:60858 0.0.0.0:* LISTEN 2039/rpc.statd
tcp 0 0 172.16.40.101:28888 172.16.40.100:53468 TIME_WAIT -
然后我自己创建socket 设置SO_REUSEPORT为1,然后bind到列表里的ip:port上,如果能bind成功证明是不是可以复用?
对于正在被复用的端口,是不是只要把上述列表里同一个ip:port,但是进程id不一样的找出来就行了?
另外,我测试了一下,SO_REUSEPORT设置后可以将多个socketbind到同一个ip:port,但是系统好像随机挑一个socket来接收连接,其他的socket虽然能bind成功,但是是收不到数据的。
这样的端口复用价值何在,有什么使用场景呢?
测试代码:
将代码编译成2个文件,然后同时运行,都是可以bind成功的,但是我telnet上来后,只有一个能收到数据。
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <unistd.h>
- #include<netinet/in.h>
- #include <arpa/inet.h>
- int SockDemo()
- {
- sockaddr_in in;
- memset(&in,'\0',sizeof(in));
- in.sin_family=AF_INET;
- in.sin_port=htons(28888);
- in.sin_addr.s_addr=htons(INADDR_ANY); // inet_addr("172.16.40.101");
-
- int reuse0=1;
- int serv=socket(AF_INET, SOCK_STREAM, 0);
- if (setsockopt(serv, SOL_SOCKET, SO_REUSEPORT, (char *)&reuse0, sizeof(reuse0))==-1) return errno;
- if (bind(serv, (sockaddr*)&in, sizeof(sockaddr)) == -1) return errno;
- if (listen(serv, 5)==-1) return errno;
- while (true)
- {
- struct sockaddr_in client_addr;
- socklen_t length = sizeof(client_addr);
- int con = accept(serv, (struct sockaddr*)&client_addr,&length);
- if (con < 0)
- {
- printf("accept failed!\n");
- }
- else
- {
- printf("accept success!\n");
- char buf[1024] = {0};
- do
- {
- int ret = recv(con, buf, 1024, 0);
- if (ret <= 0)
- {
- close(con);
- break;
- }
- else
- {
- printf(buf);
- }
- } while(true);
- }
- }
-
- close(serv);
- return 0;
-
- }
- int main(int argc, char *argv[])
- {
- int errcode=SockDemo();
- printf("errno=%d, %s.\n", errcode, strerror(errcode));
- return 0;
- }
复制代码 最后再问下SO_REUSEADDR的问题,这个在linux tcp socket上就不可能把多个socket bind到同一个ip:port上,把上面的额代码改一下就知道了。
这个SO_REUSEADDR似乎是用在服务进程重启的时候,如果之前的连接还处于time_wait状态,是可以bind成功的,这样避免等待,可以快速重启进程。除此之外,这个选项还有什么其他作用吗?
在我看来,linux下的端口复用就是上面这两个了,不知是否理解正确,望诸位大神指教! |
|