TCP客户端Socket如何立即释放端口?
|
admin
2017年4月12日 1:29
本文热度 31509
|
在做一个关于web负载均衡的压力测试的时候碰到一个问题。测试采用的是单机测试,web服务器+3个负载均衡节点服务+客户端 都在同一台4核工作机上。由于测试逻辑简单,1024个http客户端4s左右会吃光6W个端口,继续访问就会出现错误:由于系统缓冲区空间不足或队列已满,不能执行套接字上的操作。错误的原因是Socket占用的端口没有被释放,需要等待20+s才能进行下一轮测试,很浪费时间。需要说明的是,释放客户端端口不像服务器端口那样关闭Socket就可以了。客户端端口在Socket关闭之后处于Close_Wait状态,这个状态时间应该是由HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters下的TcpTimedWaitDelay键值决定的,但是这个值最小值是30s。另外可以使用API函数SetTcpEntry强行关闭连接释放端口,但是某些操作系统由于UAC的原因需要提升为管理员权限,如果通过app.manifest设置管理员身份运行,会弹出一个提升权限的对话框,作为一个性能测试的Demo弹出这样一个框感觉有点吓人。希望高人指点,如何在不需要用户参与的情况下把端口释放掉。需要具体测试代码的话可以到这里下载https://fastcsharp.codeplex.com/,测试项目为demo.loadBalancingTcpCommandWeb。
该文章在 2026/7/3 18:51:26 编辑过
| |
全部评论5 |
|
admin
2017年4月12日 1:30
发现连接数超某数时,及时清除不用套接字子线程,服务器与客户端均可设超时强制关闭
''及时清除不用的子线程。
Private Sub dogthread(ByVal Tzobj As System.Object, ByVal e As System.EventArgs)
dogrunBZ(Tzobj) = True ''正在运行时,防止重复运行
Try
mySocket(Tzobj).Shutdown(SocketShutdown.Receive) ''关闭套接字接收
''mySocket(Tzobj).Shutdown(SocketShutdown.Both) ''组态王对此条支持不好
Catch
End Try
Try
mySocket(Tzobj).Close() ''引发子线程立即异常,中断子线程循环
Catch
End Try
Try
myThread(Tzobj).Abort() ''中止某个线程,销毁这些线程,需要很多时间!
myThread(Tzobj).Join(300) ''等待300毫秒,超时也终止,防止不出来
Catch
End Try
Try
mySocket(Tzobj) = Nothing ''防止组态王响应没那么快!!!
Catch
End Try
GC.Collect()
dogrunBZ(Tzobj) = False ''运行完毕标志
End Sub
该评论在 2026/7/3 18:49:32 编辑过
|
|
admin
2017年4月12日 1:31
''及时清除不用的子线程。
Private Sub dogthread(ByVal Tzobj As System.Object, ByVal e As System.EventArgs)
dogrunBZ(Tzobj) = True ''正在运行时,防止重复运行
Try
mySocket(Tzobj).Shutdown(SocketShutdown.Receive) ''关闭套接字接收
''mySocket(Tzobj).Shutdown(SocketShutdown.Both) ''组态王对此条支持不好
Catch
End Try
Try
mySocket(Tzobj).Close() ''引发子线程立即异常,中断子线程循环
Catch
End Try
Try
myThread(Tzobj).Abort() ''中止某个线程,销毁这些线程,需要很多时间!
myThread(Tzobj).Join(300) ''等待300毫秒,超时也终止,防止不出来
Catch
End Try
Try
mySocket(Tzobj) = Nothing ''防止组态王响应没那么快!!!
Catch
End Try
GC.Collect()
dogrunBZ(Tzobj) = False ''运行完毕标志
End Sub
该评论在 2026/7/3 18:50:09 编辑过
|
|
admin
2017年4月12日 1:31
谢谢回复,真不是这么简单的事。你可以试试能不能在30s之内创建>65536个客户端连接。
该评论在 2026/7/3 18:51:02 编辑过
|
|
admin
2017年4月12日 1:32
我对tcp研究的不是那么深..请问你这个6W多连接是长连接没有断开的?不是吧client的端口也没这么多..如果是opesendclosedispose的话感觉还差不多可以..否则这也不叫长连接了啊.....难道你的意思本地client使用了5000端口连接然后这5000还可以个下一个client用?不存在啊..那么你2个client服务器如何找到客户端...
该评论在 2026/7/3 18:51:11 编辑过
|
|
admin
2017年4月12日 1:33
TcpClient c = new TcpClient();
c.Connect(IPAddress.Parse(x), o);
c.Client.Send(by);
c.Client.Shutdown(SocketShutdown.Both);
c.Client.Close();
c.Close();这虽然是tcp_client但是发了就没了.....具体我还真没测试过..不知道我想的是不是跟你想的一样..
该评论在 2026/7/3 18:50:51 编辑过
|