[转] 解决socket端口被占用的问题

本文介绍了一个关于VC6环境下TCP Socket通讯的问题,即程序结束后其绑定的端口仍处于监听状态。问题根源在于使用CreateProcess()创建子进程时设置了参数导致Socket被继承。文章详细解释了解决方案,通过使用DuplicateHandle()复制句柄并设置不可继承标志。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这段时间遇到一个棘手的问题。现象如下:

VC6工程,程序a.exe使用TCP的Socket通讯。但当程序a.exe结束后,通讯中绑定的端口会始终处于监听状态,外部地址是0.0.0.0,所属的进程PID是已经结束了的a.exe原有的PID。已经确认,a.exe在结束前已经成功调用closesocket()关闭了socket,并调用了WSAClean()。但端口依旧被占用,处于LISTENING状态。

经过长时间研究发现,问题是由于创建子进程导致的。a.exe中会通过CreateProcess()创建android的adb.exe。如果此时是第一次调用adb.exe,则adb.exe会自动创建adb-server作为常驻进程,不会自己退出。而CreateProcess()中又设置了bInheritHandles和lpProcessAttributes.bInheritHandle两个参数为TRUE,这是为了能够得到子进程的stdin/out流。

但一旦设置了这两个参数,则CreateProcess()就会使创建的子进程继承了所有父进程的句柄,包括已经创建的Socket。因此,只有当adb-server的这个adb.exe进程结束,才会释放掉占用的Socket端口。

问题找到了,解决方法如下:

创建Socket时,首先创建一个SOCKET sOld。然后调用DuplicateHandle()复制出一个新的SOCKET s。DuplicateHandle()的参数中,bInheritHandle设置为FALSE,这就复制出了一个不能被子进程继承的SOCKET;同时指定参数dwOptions为DUPLICATE_CLOSE_SOURCE,使得sOld在被复制后自动关闭。接下来使用新的s来通讯。这样,Socket就不会被继承了。问题也就解决了。注意,使用DuplicateHandle()复制SOCKET时,需要强制转换SOCKET为HANDLE类型。

### 解决Socket端口占用的方法 对于应用程序中遇到的Socket端口占用问题,可以通过多种方式进行处理和预防。针对不同平台和技术栈有不同的解决方案。 #### Windows环境下通过命令行强制释放端口 在Windows操作系统上,如果发现特定端口被其他进程意外占用,可以采用如下方法来查找并终止占用端口的服务或应用: ```batch netstat -aon | findstr :<port_number> taskkill /PID <process_id> /F ``` 上述指令中的`<port_number>`应替换为目标端口号,而`<process_id>`则是由前一条命令查询所得的结果之一[^3]。 #### Linux/Unix类系统下的解决办法 对于Linux或其他基于Unix的操作系统而言,则可利用lsof工具配合kill命令完成相同目的: ```bash sudo lsof -i:<port_number> sudo kill -9 <process_id> ``` 这里同样需要注意将占位符替换成实际数值[^4]。 #### 编程层面防止端口冲突 为了从根本上避免因服务重启而导致的端口绑定失败现象,在编写网络通信程序时应当考虑设置SO_REUSEADDR选项,允许本地地址立即重用而不必等待TIME_WAIT状态结束。这可以在创建ServerSocket实例之前执行相应配置: ```java serverSocket.setReuseAddress(true); ``` 此做法适用于Java环境;而对于Python来说则可通过socket库实现相似功能: ```python import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ``` 另外,Netty框架也提供了类似的机制让用户能够更方便地管理TCP参数,从而有效降低端口争用的风险[^2]。 #### 多线程场景下的注意事项 当涉及到多线程编程时,确保每个工作线程都能正确获取到唯一的可用端口非常重要。通常情况下,主线程负责监听外部请求并将新建立起来的连接分配给子线程去处理。此时应该注意不要让多个线程尝试同时绑定相同的端口,以免引发竞争条件造成异常情况的发生[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值