套接字绑定 returns 相同的临时端口
socket bind returns same ephemeral port
我试图通过将 0
端口值传递给套接字 bind
函数,将 256 个不同 pthread
中的 256 个不同套接字绑定到不同的端口。但有时相同的端口会绑定到不同的套接字。我从调试输出中发现了这个问题。有人可以解释为什么会这样吗?这是我的示例代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
unsigned short get_sock_name(int sock_fd) {
socklen_t sock_len = sizeof(struct sockaddr_in);
struct sockaddr_in recv_IP_sock_addr;
getsockname(sock_fd, (struct sockaddr*)&recv_IP_sock_addr, &sock_len);
return (ntohs(recv_IP_sock_addr.sin_port));
}
void* run(void *t) {
int sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);;
struct sockaddr_in recv_IP_sock_addr;
memset((char*)&recv_IP_sock_addr, '[=11=]', sizeof(struct sockaddr_in));
recv_IP_sock_addr.sin_family = AF_INET;
recv_IP_sock_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
recv_IP_sock_addr.sin_port = htons(0);
int yes = 1;
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes));
bind(sock_fd, (struct sockaddr*)&recv_IP_sock_addr, sizeof(struct sockaddr));
unsigned short port = get_sock_name(sock_fd);
printf("receiving data from port %hu\n", port);
char buff[2048];
while (1) {
ssize_t len = recvfrom(sock_fd, buff, sizeof(buff), 0, NULL, NULL);
}
}
int main() {
pthread_t pt_arr[256];
for (int i = 0; i < 256; ++i)
pthread_create(&pt_arr[i], NULL, run, NULL);
char buff[32];
fgets(buff, sizeof(buff), stdin);
}
您设置了 SO_REUSEADDR
,对于 UDP,它允许两个套接字绑定到同一个端口。这是多播所需要的。将它与单播 UDP 一起使用似乎不是一个特别好的主意。在让实现 select 端口时使用它似乎也不是一个好主意。
删除 SO_REUSEADDR
,因为它毫无意义,并且会导致 UDP 单播出现病态行为。
我试图通过将 0
端口值传递给套接字 bind
函数,将 256 个不同 pthread
中的 256 个不同套接字绑定到不同的端口。但有时相同的端口会绑定到不同的套接字。我从调试输出中发现了这个问题。有人可以解释为什么会这样吗?这是我的示例代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
unsigned short get_sock_name(int sock_fd) {
socklen_t sock_len = sizeof(struct sockaddr_in);
struct sockaddr_in recv_IP_sock_addr;
getsockname(sock_fd, (struct sockaddr*)&recv_IP_sock_addr, &sock_len);
return (ntohs(recv_IP_sock_addr.sin_port));
}
void* run(void *t) {
int sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);;
struct sockaddr_in recv_IP_sock_addr;
memset((char*)&recv_IP_sock_addr, '[=11=]', sizeof(struct sockaddr_in));
recv_IP_sock_addr.sin_family = AF_INET;
recv_IP_sock_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
recv_IP_sock_addr.sin_port = htons(0);
int yes = 1;
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes));
bind(sock_fd, (struct sockaddr*)&recv_IP_sock_addr, sizeof(struct sockaddr));
unsigned short port = get_sock_name(sock_fd);
printf("receiving data from port %hu\n", port);
char buff[2048];
while (1) {
ssize_t len = recvfrom(sock_fd, buff, sizeof(buff), 0, NULL, NULL);
}
}
int main() {
pthread_t pt_arr[256];
for (int i = 0; i < 256; ++i)
pthread_create(&pt_arr[i], NULL, run, NULL);
char buff[32];
fgets(buff, sizeof(buff), stdin);
}
您设置了 SO_REUSEADDR
,对于 UDP,它允许两个套接字绑定到同一个端口。这是多播所需要的。将它与单播 UDP 一起使用似乎不是一个特别好的主意。在让实现 select 端口时使用它似乎也不是一个好主意。
删除 SO_REUSEADDR
,因为它毫无意义,并且会导致 UDP 单播出现病态行为。