在 Linux 内核 4.19 中,我有两个 UDP 套接字,它们使用 SO_REUSEPORT 绑定到同一个本地地址。我还将一个套接字(使用 connect(2))连接到远程地址,另一个套接字连接到远程地址。
使用 SO_REUSEPORT 绑定到 。我还将 连接 到远程地址,另一个套接字未 连接 。让远程套接字始终向本地发送消息。
我想要的现象是数据总是被已经连接的套接字接受。 但实际情况是,根据两个套接字的创建顺序,当先创建连接的套接字,后创建未连接的套接字时,数据总是发送到后创建的套接字(没有连接)。当创建顺序颠倒时,数据总是发送到先创建的套接字(有连接)。 这是一个错误吗?
在 Linux 内核 5.15 中,无论套接字的创建顺序如何,数据始终通过 connect 发送到套接字。 这正是我希望的。
运行以下代码程序将始终打印:listenfd recv
例子 :
#include<iostream>
#include<string.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <thread>
using namespace std;
int listenfd = 0, connfd = 0, clientfd = 0, efd;
int server_port = 6666, client_port = 5555;
char server_ip[] = "127.0.0.1", client_ip[] = "127.0.0.1";
void setFd(int fd, int property){
int sockopt = 1;
setsockopt(fd, SOL_SOCKET, property, (void* )&sockopt, sizeof(sockopt));
}
void setNonBlock(int fd) {
int flags = fcntl(fd, F_GETFL, 0);
int r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
void updateEvents( int fd, int events, int op) {
struct epoll_event ev;
memset(&ev, 0, sizeof(ev));
ev.events = events;
ev.data.fd = fd;
int r = epoll_ctl(efd, op, fd, &ev);
}
void addEvent(int fd) {
updateEvents(fd, EPOLLIN, EPOLL_CTL_ADD);
}
void delEvent(int fd) {
updateEvents(fd, EPOLLIN, EPOLL_CTL_DEL);
}
void startfd(int &fd, struct sockaddr_in& bind_addr, struct sockaddr_in& conn_addr, bool conn) {
if(fd) {
delEvent(fd);
close(fd);
fd = 0;
}
fd = socket(AF_INET, SOCK_DGRAM, 0);
setFd(fd,SO_REUSEADDR);
setFd(fd,SO_REUSEPORT);
setNonBlock(fd);
int r = ::bind(fd, (struct sockaddr *)&bind_addr, sizeof(struct sockaddr));
if(conn) {
connect(fd , (struct sockaddr * )&conn_addr, sizeof(struct sockaddr));
}
addEvent(fd);
}
void e_loop() {
for(;;) {
const int kMaxEvents = 20;
struct epoll_event activeEvs[100];
int n = epoll_wait(efd, activeEvs, kMaxEvents, 10000);
for (int i = 0; i < n; i++) {
int fd = activeEvs[i].data.fd;
int events = activeEvs[i].events;
if (events & (EPOLLIN | EPOLLERR)) {
char s[10];
int recv_n = recv(fd, s, 10, 0);
if(fd == listenfd) {
cout << "listenfd recv\n";
} else if(fd == connfd) {
cout << "connfd recv\n";
}
}
}
}
}
int main() {
efd = epoll_create(1);
thread t(e_loop);
struct sockaddr_in caddr, saddr;
memset(&caddr, 0, sizeof caddr);
memset(&saddr, 0, sizeof saddr);
caddr.sin_family = AF_INET;
saddr.sin_family = AF_INET;
caddr.sin_port = htons(client_port);
saddr.sin_port = htons(server_port);
caddr.sin_addr.s_addr = inet_addr(client_ip);
saddr.sin_addr.s_addr = inet_addr(server_ip);
startfd(connfd, saddr, caddr, true);
startfd(listenfd, saddr, caddr, false);
startfd(clientfd, caddr, saddr, true);
while(1) {
getchar();
send(clientfd, "", 0, 0);
}
}
UDP 数据包到达错误套接字并带有 SO_REUSEPORT
下载声明:
本站所有软件和资料均为软件作者提供或网友推荐发布而来,仅供学习和研究使用,不得用于任何商业用途。如本站不慎侵犯你的版权请联系我,我将及时处理,并撤下相关内容!