如何为TCP SOCK_STREAM类型socket自定义指定源端口(本地端口)
实现方案
要为TCP socket指定自定义源端口,你只需要在创建socket之后、调用connect()之前,新增bind()绑定本地地址的逻辑即可,具体修改如下:
核心修改步骤
- 创建socket之后,构造
sockaddr_in类型的本地地址结构体,指定你要使用的源端口,如果不需要指定固定源IP可以将地址字段设为INADDR_ANY让系统自动选择出口网卡IP - 调用
bind()函数将当前socket和构造的本地地址绑定,注意判断返回值处理端口占用等异常情况 - 完成绑定后再执行原有
connect()逻辑即可
修改后的完整代码
if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { continue; } // Set it in nonblocking mode fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); // -------------------新增 绑定自定义源端口逻辑开始------------------- struct sockaddr_in local_addr = {0}; local_addr.sin_family = AF_INET; local_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 不需要指定源IP的话用INADDR_ANY即可 // 替换1234为你要指定的源端口,注意要用htons转网络字节序 local_addr.sin_port = htons(1234); if (bind(fd, (struct sockaddr *)&local_addr, sizeof(local_addr)) == -1) { // 绑定失败通常是端口被占用、权限不足(比如1024以下端口需要root权限)等原因,可根据业务需要处理错误 close(fd); continue; } // -------------------新增 绑定自定义源端口逻辑结束------------------- // Set up address to connect to addr.sin_family = AF_INET; if (targs[i].netmask < 32) addr.sin_addr.s_addr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask)); else addr.sin_addr.s_addr = targs[i].addr; if (dport == 0xffff) addr.sin_port = rand_next() & 0xffff; else addr.sin_port = htons(dport); connect(fd, (struct sockaddr *)&addr, sizeof (struct sockaddr_in)); usleep(1000000); start_recv = time(NULL);
注意事项
- 你指定的源端口必须未被其他进程占用,且如果要使用1024以下的特权端口,需要进程有root权限
- 如果需要随机使用某一范围内的源端口,可以在绑定失败时循环更换端口重试
- 如果需要同时指定固定源IP,将
local_addr.sin_addr.s_addr替换为对应源IP的网络字节序值即可
内容的提问来源于stack exchange,提问作者Mohamed Abdel Fattah
相关产品推荐
相关产品推荐

