SO_REUSEPORT 端口复用
四元组 (local ip,local port, remote ip, remote port)
测试条件,local ip,local port 一样,remote port不一样
即多个进程使用同一个本地端口,发起多个tcp连接
server.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<sys/wait.h>
#include<string.h>
#define SIZE 30
void read_child(int signo);
int main(int argc,char *argv[])
{
int server_sock,client_sock,r;
struct sockaddr_in server_addr,client_addr;
pid_t pid;
struct sigaction act;
socklen_t len;
char buf[SIZE];
if(argc!=2)
{
printf("need port\n");
return 1;
}
act.sa_handler=read_child;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
if(-1 == sigaction(SIGCHLD,&act,0))
{
printf("sigaction error\n");
return -1;
}
server_sock = socket(AF_INET,SOCK_STREAM,0);
memset(&server_addr,0,sizeof server_addr);
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(atoi(argv[1]));
if(-1 == bind(server_sock, (struct sockaddr*)&server_addr,sizeof(server_addr)))
{
printf(" bind error\n");
return -1;
}
if(-1 == listen(server_sock, 10))
{
printf(" listen error\n");
return -1;
}
while(1)
{
len=sizeof client_addr;
client_sock=accept(server_sock,(struct sockaddr*)&client_addr,&len);
if(client_sock == -1)
continue;
pid=fork();
if(pid == -1)
{
close(client_sock);
continue;
}
else if(pid == 0)
{
close(server_sock);
memset(buf,0,SIZE);
for (;;) {
r = read(client_sock,buf,SIZE-1);
if (r <=0 ) {
break;
}
buf[r]='\0';
write(client_sock,buf,strlen(buf));
printf("client ip: %s ,port: %d, recv: %s\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port), buf);
}
return 0;
}
else
{
printf("new client ip: %s ,port: %d,child pid=%d\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),pid);
close(client_sock);
}
}
close(server_sock);
return 0;
}
void read_child(int signo){
if(signo == SIGCHLD)
{
int status;
pid_t pid=waitpid(-1,&status,WNOHANG);
printf("remove child pid:%d\n",pid);
}
}
client.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<sys/wait.h>
#include<string.h>
#define SIZE 30
int main(int argc,char *argv[])
{
if (argc != 3) {
return 0;
}
int sock,r;
struct sockaddr_in server_addr,client_addr;
socklen_t len;
char buf[SIZE];
sock = socket(AF_INET,SOCK_STREAM,0);
memset(&server_addr,0,sizeof server_addr);
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=inet_addr(argv[1]);
server_addr.sin_port=htons(atoi(argv[2]));
memset(&client_addr,0,sizeof client_addr);
client_addr.sin_family=AF_INET;
client_addr.sin_addr.s_addr=inet_addr("0.0.0.0"); //127.0.0.1
client_addr.sin_port=htons(20001);
int reuse = 1;
r = setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse));
if (r==-1) {
printf("setsockopt -1\n");
return 0;
}
if(-1 == bind(sock, (struct sockaddr*)&client_addr,sizeof(client_addr)))
{
printf(" bind error\n");
return -1;
}
if(-1 ==connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)))
{
printf(" connect error\n");
return -1;
}
while(1)
{
write(sock, "hello", 5);
sleep(1);
}
return 0;
}
起两个tcp server,分别监听8000 8001
[root@localhost tcp]# ./server 8000
[root@localhost tcp]# ./server 8001
起两个tcpclient,都使用同一个本地端口20001
[root@localhost tcp]# ./client 127.0.0.1 8000 &
[1] 55225
[root@localhost tcp]# ./client 127.0.0.1 8001 &
[2] 55233
[root@localhost client]# lsof -i:20001
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
client 55225 root 3u IPv4 947728 0t0 TCP localhost:microsan->localhost:irdmi (ESTABLISHED)
server 55226 root 4u IPv4 944628 0t0 TCP localhost:irdmi->localhost:microsan (ESTABLISHED)
client 55233 root 3u IPv4 947861 0t0 TCP localhost:microsan->localhost:vcom-tunnel (ESTABLISHED)
server 55234 root 4u IPv4 944749 0t0 TCP localhost:vcom-tunnel->localhost:microsan (ESTABLISHED)
[root@localhost client]# netstat -antp| grep 20001
tcp 0 0 127.0.0.1:8000 127.0.0.1:20001 ESTABLISHED 55226/./server
tcp 0 0 127.0.0.1:8001 127.0.0.1:20001 ESTABLISHED 55234/./server
tcp 110 0 127.0.0.1:20001 127.0.0.1:8000 ESTABLISHED 55225/./client
tcp 100 0 127.0.0.1:20001 127.0.0.1:8001 ESTABLISHED 55233/./client
参考
//https://www.cnblogs.com/yikoulinux/p/13946821.html
//https://blog.csdn.net/jasonliuvip/article/details/22591531

浙公网安备 33010602011771号