UDP错误10054:远程主机强迫关闭了一个现有的连接

在UDP通信中,客户端突然断开可能导致服务器异常并影响所有客户端。本文介绍了一个常见问题,即SocketException错误ID 10054,并提供了解决方案,通过正确设置参数避免服务崩溃。

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

原文地址:http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic1887.aspx

在公司一项目的UDP消息服务开发中时不时的会遇到这样一个问题:在UDP通信过程中,如果客户端中途断开,服务器会收到一个SocketException,错误ID为10054,描述是“远程主机强迫关闭了一个现有的连接”,紧接着的事就可怕了,UDP服务终止监听,所有客户端都受到了影响。也就是说一个客户端引起的异常导致了整个系统的崩溃。这个问题可是太严重了。

地球人都知道,UDP是无连接的,怎么会出现这个异常呢?百度了一圈,发现有这个问题的现象还不少,可就是没有一个有效的回复。再GOOGLE一圈,有点眉目了。找到了一个微软的解释和一个DOTNET的解决方法:

微软的解释:http://support.microsoft.com/kb/263823

DOTNET的处理方法:http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic1887.aspx

不过处理方法似乎对参数的设置不太正确: 
byte[] optionInValue = { Convert.ToByte(true) }; 
byte[] optionOutValue;

按照这样设置还是会抛出该异常。 
首先,根据微软的解释,optionInValue 传入的应该是false,而不是true; 
其次,根据微软的解释,optionOutValue应该是一个DWORD值,不应不赋值,或设为null。

根据以上两点,将以上两句改为: 
byte[] optionInValue = { Convert.ToByte(false) }; 
byte[] optionOutValue = new byte[4];

经过测试,模拟500个用户进行登录、收发消息、注销、异常退出、再连接,均没有再抛出该异常。服务表现稳定。

在UDP通信过程中,如果客户端中途断开,服务器会收到一个SocketException,错误ID为10054,描述是“远程主机强迫关闭了一个现有的连接”,紧接着的事就可怕了,UDP服务终止监听,所有客户端都受到了影响。也就是说一个客户端引起的异常导致了整个系统的崩溃。

找了好几天了。终于找到了解决办法。

在初始化对象后设置属性如下:

uint IOC_IN = 0x80000000; 
uint IOC_VENDOR = 0x18000000; 
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; 
ClientSocket.IOControl((int)SIO_UDP_CONNRESET, new byte[] {Convert.ToByte(false)}, null);

Socket.IOControl 方法 (IOControlCode, Byte[], Byte[])

使用 IOControlCode 枚举指定控制代码,为 Socket 设置低级操作模式。

参数

ioControlCode

一个 IOControlCode 值,它指定要执行的操作的控制代码。

optionInValue

Byte 类型的数组,包含操作要求的输入数据。

optionOutValue

Byte 类型的数组,包含由操作返回的输出数据。

返回值

optionOutValue 参数中的字节数。

异常类型 
条件

SocketException

试图访问套接字时发生错误。有关更多信息,请参见备注部分。

ObjectDisposedException

Socket 已关闭。

InvalidOperationException

试图不使用 Blocking 属性更改阻止模式。

此方法提供对 Socket 类的当前实例所基于的操作系统 Socket 的低级访问。有关更多信息,请参见 MSDN Library 中的 WSAIoctl 文档。

本人体会:

再做通信项目中无意中遇到了这个问题,记得上学的时候老师说过UDP是无连接的,但是在项目中遇到了这个远程主机强制关闭现有连接的错误,搞得一头雾水,什么也不用说,马上google一下,发现很多朋友都有遇到了这个问题,最后还是看到了原作者的这篇文章后解决了问题,呵呵,再次转载过来,希望帮助所有遇到这个问题的朋友快速的解决问题。

### 关于邮件交付时出现“远程主机强迫关闭一个现有连接”的错误原因 在探讨邮件交付过程中遇到的“远程主机强迫关闭一个现有连接”这一现象时,可以从多个角度来理解其背后的技术原理。 #### 连接管理机制 当两台计算机通过 socket 建立起通信连接之后,实际上该 socket 主要承担两项职责:接收数据以及发送数据,在没有数据交互的时候则处于等待状态[^1]。如果在这个期间发生了异常情况,比如服务器端主动终止了与客户端之间的会话,则可能会触发此类警告信息。 #### 协议层面的因素 考虑到电子邮件通常依赖于特定的应用层协议(如 SMTP),而这些应用层协议又是基于更底层的传输层协议工作的。其中,TCP 是一种面向连接且具有高可靠性的传输控制协议;相比之下,UDP 则不具备这种特性[^2]。因此,对于像SMTP这样的服务来说,大多数情况下会选择更为稳定的 TCP 来保障消息传递的安全性和准确性。然而,即使是在使用 TCP 的情形下,仍然可能出现由于网络状况不佳或者其他因素引起的意外断开事件。 #### 可能的具体成因 - **资源超载**:目标邮箱所在的服务器可能因为处理过多请求而导致性能下降甚至崩溃,从而不得不强制结束部分现有链接以维持正常运作。 - **安全策略**:某些防火墙或入侵检测系统为了防止潜在威胁,会在监测到可疑活动时立即切断相关联机路径。 - **配置不当**:无论是本地还是远端设备上的设置失误都可能导致不正常的连接中断行为发生。 - **版本兼容性问题**:不同软件间可能存在差异化的实现细节,这有时也会造成意想不到的结果。 ```python import smtplib from email.mime.text import MIMEText def send_email(): try: server = smtplib.SMTP('smtp.example.com', 587) server.starttls() server.login("username", "password") msg = MIMEText("This is a test message.") msg['Subject'] = 'Test Email' msg['From'] = 'sender@example.com' msg['To'] = 'recipient@example.com' server.sendmail(msg['From'], [msg['To']], msg.as_string()) server.quit() except Exception as e: print(f"An error occurred while sending the email: {e}") send_email() ``` 上述代码展示了如何利用 Python 发送一封简单的测试邮件,并包含了基本的异常捕获逻辑以便更好地应对各种突发状况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值