概述
这段时间遇到一个棘手的问题。现象如下:
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端口被占用的问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复