故事是这样的。
前几天在网上逛,看到了一个漂亮的坦克模型。
我觉得这个坦克可以做一个游戏,那需要一些服务器代码。
因为是实时对战的,听说TCP有很多不适,选择了UDP。
得知有一种算法可以解决UDP丢包乱序的问题,就封装成了C#,雄赳赳气昂昂准备大搞一番。
然而和客户端一对接,Client发了几个包关闭,天,这就抛了个异常!
10054...远程主机强迫关闭了一个现有的连接
喂喂,不是说好的UDP是无连接的吗?为嘛说连接被强迫关闭了??
不过没关系,不就是10054吗,TCP Socket时候又不是没见过,try catch一下就好了。
那么,try catch(ex){log(ex);} finally{beginReceive();}三步走。
晕!beginReceive()挂了...这都会挂?再加try catch捕获了递归,递归到成功为止!然而怎么救也救不回来/(ㄒoㄒ)/~~
仔细检查一下,发现是对关闭的客户端EndPoint执行了Send,导致Receive那边抛出了异常Σ( ° △ °|||)︴
为嘛是执行Send导致Receive抛出异常,而且导致next Receive救也救不回来?
那么?不Send能救吗?能...可是问题是当Receive异常的时候不知道是哪个客户端断开了呀,如果是Send时候异常还好,跑Receive异常,而且异常时候的EndPoint也是对不上的,关联不上啊(这时候倒是想起无连接了←_←)。
于是请教了谷歌老师。
果然搜出一大堆结果,在筛选掉大量的TCP10054和没有结果没有意义的问答贴和大量转载之后,终于找到了个靠谱的答案,不幸的是文章也是机器人爬来的转载各种广告不忍直视,好在贴出了一个链接:
https://support.microsoft.com/zh-cn/kb/263823
看这个排版,想来也是年代已久,大概意思是windows的一个bug,可以通过加几行代码的方式搞定。
于是加了几行代码:
const uint IOC_IN = 0x80000000;
int IOC_VENDOR = 0x18000000;
int SIO_UDP_CONNRESET = (int)(IOC_IN | IOC_VENDOR | 12);
//因为我使用的是UdpClient, 所以先get出Socket(Client)来。
server.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
再次执行,OK,说好的无连接UDP回来了!
问题解决。
Linux下无此问题,所以不需要添加上述代码,(添加反而异常)。
鉴于网上答案诸多不靠谱,立此贴增加点命中率。