hgoldfish / qtnetworkng

QtNetwork Next Generation. A coroutine based network framework for Qt/C++, with more simpler API than boost::asio.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

win10下sslsocket有可能会连不上ubuntu 18.04 linux服务器

liuxiandeng opened this issue · comments

win10下使用sslsocket客户端去连接ubuntu 18.04 服务器(虚拟机)有可能会连不上。但是将同一套代码的客户端和服务器都部署在同一台win10机器上是能客户端是能连上服务器的。将同一套代码的客户端和服务器都部署在同一台ubuntu 18.04机器上也能连上。以上描述都是指的TCP连接

后来我尝试追踪,发现win10下sslsocket客户端调用WSAConnect返回值是WSAEWOULDBLOCK,微软帮助文档上说:“对于非阻塞套接字,连接尝试无法立即完成。在这种情况下, WSAConnect将返回 SOCKET_ERROR,而 WSAGetLastError将返回 WSAEWOULDBLOCK,可以使用 select通过检查套接字是否可写来确定连接请求的完成”。也就是说WSAEWOULDBLOCK是一个正常返回值,并不一定代表出错,您这个位置的处理可能有问题。

使用微软提供的思路我修改了一下代码,win10客户端就能连上ubuntu 18.04 服务器,但是我写的代码不规范,不好意思贴出来,您有时间的时候可以修复一下这个问题。

附:微软帮助文档链接:https://docs.microsoft.com/zh-hk/windows/win32/api/winsock2/nf-winsock2-wsaconnect
附:CSDN网友类似博文:https://blog.csdn.net/nyist327/article/details/45918769

我当时是在win10 和 ubuntu18.04两台物理机器下测试出来的这个问题。客户端和服务器在同一个win10机器下是测不出这个问题的,因为WSAConnect立刻就返回了成功,不会返回WSAEWOULDBLOCK这个错误码,在win10物理机以及win10物理机里面安装的虚拟机ubuntu 18.04这种环境下也能测试出这个问题。
最后,客户端、服务器代码以及相关代码,如果您需要的话,我都能提供。

奇怪啊。。按说 qtng 对这个是有处理的。是不是防火墙之类原因。我们的生产服务器就是 ubuntu 18.04,客户端都是 win7 和 win10.

相关的处理代码在这里:

https://github.com/hgoldfish/qtnetworkng/blob/master/src/socket_win.cpp#L591

防火墙两端都是关闭的,我检查过,并且用wireshark抓包过,显示问题出在TCP的第三次握手上,客户端给服务器发送了一个RST,TCP的三次握手是发生在调用connect函数之后,由此我才想着追踪一下WSAConnect函数。

看了微软帮助文档和qtng这个位置代码,我觉得qtng这个位置的处理是有问题的,WSAEWOULDBLOCK错误码表示正在连接中,还并未完成,所以应该稍微等一等再去调用getsockopt,qtng这个位置是立刻去调用getsockopt,微软帮助文档让使用select函数,使用select函数也是需要设置超时时间的,本质上还是需要等待一个超时时间;其次,SOL_SOCKET的SO_ERROR选项是不支持setsockopt函数的,这个位置也有问题,不能调用setsockopt函数;第三,在返回WSAEWOULDBLOCK(也就是正在连接中)去调用setsockopt会返回 WSAEALREADY,这一点在我给您发的微软链接上刚好有体现。

最后说明下,修改这个位置后,确实每次都能连上了

有完整的最小测试代码吗?

从 socket_win.cpp 的代码看,getsockopt()调用之后,只要是没找到连接关闭的错误,都会break switch然后调用 watcher.start(),而watcher.start()实际上是个WSAAsyncSelect()调用。所以这样是符合 MSDN 文档的。

不过我看了那段代码之后,仍然修改了一下,上传了新代码到 github,可以更新一下,看有没有解决问题。

之前的代码逻辑是只要WSAEWOULDBLOCK就调用getsockopt() 看看是不是连接错误了。更新后的代码逻辑是第二次碰到WSAEWOULDBLOCK才会调用getsockopt(),第一次直接跳到watcher.start()先等待一次再说。这样子做的话,通常能够减少两次系统调用,提高性能。

github上最新代码也还是没能解决这个问题,最小测试代码只有连接部分,稍后发您邮箱,这个完全不着急,您可以有时间在看,最好是将server放在Ubuntu下,将客户端放在windows下,因为我这边是这样才重现这个问题的

被您那边拒收了,当成了垃圾邮件,所以上传至百度网盘了
链接:https://pan.baidu.com/s/1dzFbIN0dGZnOsOqAT-HUUw
提取码:krzi
--来自百度网盘超级会员V5的分享

我们的生产环境就是 ubuntu 18.04,加客户端 windows 7, windows 10. 跟你的一样。暂时没有观察到这样的现象,所以觉得很奇怪。

加个微信我跟你说说你代码里面好像有一些问题。可能需要改一下。我wx号是 hgoldfish

是我代码的问题,谢谢作者大佬的耐心帮助,收获颇多,再次谢谢作者大佬,鞠躬