TCP客户端Socket主动断开如何立即释放端口?

showjim 2014-11-12 11:05:42
我有一个web端富文本编辑器处理粘帖URL转换成标题的需求,使用到了服务器端的HTML标题抓取的组件。由于系统释放端口的最小时间为30s,这样就限制了抓取并发量,上限是2000/s左右。而且一旦超限,会引起其它需要端口的应用错误。
在这个帖子中TCP客户端Socket如何立即释放端口?解决了一个Demo测试的问题,本以为这个问题会一并解决掉。而这个组件为了减少带宽提高吞吐量,没有下载整个页面,而是扫描到title就主动断开连接,所以有了这个新问题。

当然这个组件在实际使用中是可以使用管理员身份或者以windows服务的方式启动,但是不方便自动部署与更新,需要手动操作。
现在的问题有两个,解决其中一个就可以了:一个看帖子标题(主动断开),一个问题是如何简单的绕过管理员权限问题。
...全文
6829 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
我现在在路上 2014-11-13
  • 打赏
  • 举报
回复
引用 5 楼 sbwwkmyd 的回复:
我现在两个问题都采用非安全断开的方案,因为这两个情景都适应。
showjim 2014-11-12
  • 打赏
  • 举报
回复
我现在两个问题都采用非安全断开的方案,因为这两个情景都适应。
我现在在路上 2014-11-12
  • 打赏
  • 举报
回复
引用 3 楼 sbwwkmyd 的回复:
[quote=引用 1 楼 ta_wuhen 的回复:] 那个,我想到可以变相的重用端口。 初始化socket的时候,在绑定至地址前,使用 Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 来设置地址复用。
这个确实有一点作用,但是不能彻底解决问题,而且程序逻辑麻烦,所以放弃了这种方案。[/quote] 额,那你现在是什么方案。。
showjim 2014-11-12
  • 打赏
  • 举报
回复
引用 1 楼 ta_wuhen 的回复:
那个,我想到可以变相的重用端口。 初始化socket的时候,在绑定至地址前,使用 Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 来设置地址复用。
这个确实有一点作用,但是不能彻底解决问题,而且程序逻辑麻烦,所以放弃了这种方案。
我现在在路上 2014-11-12
  • 打赏
  • 举报
回复
引用“特别的TIME_WAIT状态: 从以上TCP连接关闭的状态转换图可以看出,主动关闭的一方在发送完对对方FIN报文的确认(ACK)报文后, 会进入TIME_WAIT状态。TIME_WAIT状态也称为2MSL状态。 什么是2MSL?MSL即Maximum Segment Lifetime,也就是报文最大生存时间,引用<TCP/IP详解>中的话:“ 它(MSL)是任何报文段被丢弃前在网络内的最长时间。”那么,2MSL也就是这个时间的2倍。其实我觉得没 必要把这个MSL的确切含义搞明白,你所需要明白的是,当TCP连接完成四个报文段的交换时,主动关闭的 一方将继续等待一定时间(2-4分钟),即使两端的应用程序结束。你可以写代码试试,然后用netstat查看下。 为什么需要2MSL?根据<TCP/IP详解>和<The TCP/IP Guide>中的说法,有两个原因: 其一,保证发送的ACK会成功发送到对方,如何保证?我觉得可能是通过超时计时器发送。这个就很难用 代码演示了。 其二,报文可能会被混淆,意思是说,其他时候的连接可能会被当作本次的连接。直接引用<The TCP/IP Guide> 的说法:The second is to provide a “buffering period” between the end of this connection and any subsequent ones. If not for this period, it is possible that packets from different connections could be mixed, creating confusion. TIME_WAIT状态所带来的影响: 当某个连接的一端处于TIME_WAIT状态时,该连接将不能再被使用。事实上,对于我们比较有现实意义的 是,这个端口将不能再被使用。某个端口处于TIME_WAIT状态(其实应该是这个连接)时,这意味着这个TCP 连接并没有断开(完全断开),那么,如果你bind这个端口,就会失败。 对于服务器而言,如果服务器突然crash掉了,那么它将无法再2MSL内重新启动,因为bind会失败。解决这 个问题的一个方法就是设置socket的SO_REUSEADDR选项。这个选项意味着你可以重用一个地址。 对于TIME_WAIT的插曲: 当建立一个TCP连接时,服务器端会继续用原有端口监听,同时用这个端口与客户端通信。而客户端默认情况 下会使用一个随机端口与服务器端的监听端口通信。有时候,为了服务器端的安全性,我们需要对客户端进行 验证,即限定某个IP某个特定端口的客户端。客户端可以使用bind来使用特定的端口。 对于服务器端,当设置了SO_REUSEADDR选项时,它可以在2MSL内启动并listen成功。但是对于客户端,当使 用bind并设置SO_REUSEADDR时,如果在2MSL内启动,虽然bind会成功,但是在windows平台上connect会失败。 而在linux上则不存在这个问题。(我的实验平台:winxp, ubuntu7.10) 要解决windows平台的这个问题,可以设置SO_LINGER选项。SO_LINGER选项决定调用close时,TCP的行为。 SO_LINGER涉及到linger结构体,如果设置结构体中l_onoff为非0,l_linger为0,那么调用close时TCP连接 会立刻断开,TCP不会将发送缓冲中未发送的数据发送,而是立即发送一个RST报文给对方,这个时候TCP连 接就不会进入TIME_WAIT状态。 如你所见,这样做虽然解决了问题,但是并不安全。通过以上方式设置SO_LINGER状态,等同于设置SO_DONTLINGER 状态。 断开连接时的意外: 这个算不上断开连接时的意外,当TCP连接发生一些物理上的意外情况时,例如网线断开,linux上的TCP实现 会依然认为该连接有效,而windows则会在一定时间后返回错误信息。 这似乎可以通过设置SO_KEEPALIVE选项来解决,不过不知道这个选项是否对于所有平台都有效。” 这里的SO_REUSEADDR是C/C++的,在C#中用上面的方式。
我现在在路上 2014-11-12
  • 打赏
  • 举报
回复
那个,我想到可以变相的重用端口。 初始化socket的时候,在绑定至地址前,使用 Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 来设置地址复用。

110,545

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧