10061 socket错误的猜想

时间:2022-02-06 23:56:02
10061错误,大家都知道,“由于目标机器积极拒绝,无法连接。 ”
许多解释都是表面的解释原因,说服务器端口没开等,防火墙阻挡等,其实,我遇到的问题并不是这样,看看我这个问题:

我做的是一个IOCP服务器程序跑在本机,同时我在本机有做了个client端程序,该client端程序用个循环不停的大量的连(调用connect函数)本机的IOCP服务器程序,若只跑client端程序的一个副本,一直连,没问题,但若跑client端程序的两个副本,一起连服务器,然后再杀死一个client副本,再一次启动client端的副本,这样折腾个1-2次,突然之间连接到服务器的client端就报10061错误,并且从此之后再也无法连接上IOCP服务器,我也很不理解为什么就突然连不上服务器了,于是我做了如下测试并做了猜想,这里也盼望高手给以解答:

(1)因为IOCP服务器和client都跑在本机,client端关闭了几次又重新运行几次,这样折腾了几个来回,导致client端程序的人为杀死影响了IOCP服务器程序对资源的需求(也许是IOCP服务器需要的一些网络资源被client占去)。
(2)我发现IOCP服务器此时的监听端口已经没有了,因为监听端口没了,所以client端连接肯定出10061错误。
(3)难道是我无意之间关闭了用来listen的socket?我把所有closesocket的地方全部作了判断,发现并没有close过服务器端的这个监听socket。
(4)我用的是acceptex来实现的iocp,难道acceptex的没有投递的缘故?经过测试,即使acceptex没有投递,正常情况下client仍然可以连接到IOCP服务器上去,只不过是无法收发信息罢了。

请各位朋友不吝啬赐教!

12 个解决方案

#1


关注

#2


WSAECONNREFUSED(10061)
No connection could be made because the target computer actively refused it. This usually results from trying to connect to a service that is inactive on the foreign host—that is, one with no server application running. 

不知道你的“杀死一个client副本”是如何操作的,但最后造成的结果是server不再监听了

#3


以前见过一次,我是服务器连接后马上关闭掉刚建立好的连接。

#4


问题补充:
(1)今日测试发现只要开两个client不停的连,那么只要这两个client程序(dos)窗口的有一个关闭,则另外一个的socket连接就出现10061错误。但是,已经连接上去的socket可以正常通讯,说明完成端口线程没有被意外退出,请看我的socket client端核心代码,非常粗糙,主要为测试:

//创建socket的循环等都省略
for( k1 = 0; k1 < CESHIXIBIAO; k1++) //500000
{
if( k1 !=0  && k1 % 5000 == 0)
Sleep(10000);
if (connect(sClient[k1], (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("connect() failed: %d, faile number is:%d\n", WSAGetLastError(),k1);
Sleep(5000);
//同时释放前面的某个
closesocket(sClient[k1 - 1000]);
//return 1;
continue;
}
else
{
printf("connect() success: number is:%d-----------------------\n", k1);
//return 1;
continue;
}
}

(2)杀死一个client副本的操作方法我是通过直接点DOS黑窗口右上角的X来关闭
(3)另外我杀死client的时机正好也是client执行代码拼命不断的连接server的时候,但通过client代码大家也能看到,我client只是不断连接服务器并保持住连接不切断,但并不向服务器发送任何信息。

#5


经过跟踪这种AcceptEX实现方式的IOCP,AcceptEX的实现方式和传统的accept是不太一样的,我竟然发现当client端拼命发起多个连接来连接服务器的时候杀掉整个client端(任务管理器中直接杀进程),可能会造成服务器在AcceptEX处理之前连接上又断掉(这些连接请求会保存在Listen socket的连接请求队列中),这个时候我发现服务器端GetQueuedCompletionStatus函数会返回0,表失败,同时,我发现GetLastError()返回的是64错误,这个表示指定的网络名不再可用错误,这个一般来讲都正常,因为你client端突然断开,所有连接到server的连接会导致服务器端产生大量的GetQueuedCompletionStatus返回0的情况,但是:

奇怪的问题是,在这些GetQueuedCompletionStatus返回0的情况中,我居然发现了listen套接字的socket句柄也在其中(我改了下整个程序,从而绝不closesocket,保证listen套接字绝对不是因为服务器程序closesocket引起),当listen套接字的socket句柄在其中的时候,server端监听端口消失,client也就再也无法连接。
各位朋友分析到过这种情况没?

#6


难题解决,我理解错误。
GetQueuedCompletionStatus返回0,错误代码为64。
注意,我是每收到一个正常的ACCEPT请求后才在ACCEPT请求代码中再发起一个新的AcceptEx投递。

这里有个技术点,就是正常连接进来的socket会执行一系列ACCEPT请求代码(这些代码当然是由你写的),但若client拼命连接server,然后突然之间client端又被关闭,则服务器端会出现两种socket,这两种socket都是GetQueuedCompletionStatus返回0,错误代码为64的。
第一种就是已经正常连接进来的socket,这些正常连接进来的socket,我们只需要closesocket把他们关闭就行了,因为他们已经正常的执行了我的ACCEPT请求代码。

第二种就是“保存在Listen socket的连接请求队列中”的client socket,这些socket还没有来得及执行ACCEPT事件代码就被突然关闭的client端导致产生了GetQueuedCompletionStatus返回0,并且错误代码为64的错误,这种错误,我们的处理步骤是2个:
(1)关闭这个socket。
(2)发起新的AcceptEx请求以保证该IOCP线程可以收到新的连入请求。

#7


楼主的钻研精神令人佩服!学习了,

#8


结贴通知:
请lz注意结贴。。。。

#9


遇到相同的问题 学习了

#10


遇到相同的问题 学习了

#11


遇到相同的问题 学习了

#12


遇到相同的问题,感谢楼主给了个思路!

#1


关注

#2


WSAECONNREFUSED(10061)
No connection could be made because the target computer actively refused it. This usually results from trying to connect to a service that is inactive on the foreign host—that is, one with no server application running. 

不知道你的“杀死一个client副本”是如何操作的,但最后造成的结果是server不再监听了

#3


以前见过一次,我是服务器连接后马上关闭掉刚建立好的连接。

#4


问题补充:
(1)今日测试发现只要开两个client不停的连,那么只要这两个client程序(dos)窗口的有一个关闭,则另外一个的socket连接就出现10061错误。但是,已经连接上去的socket可以正常通讯,说明完成端口线程没有被意外退出,请看我的socket client端核心代码,非常粗糙,主要为测试:

//创建socket的循环等都省略
for( k1 = 0; k1 < CESHIXIBIAO; k1++) //500000
{
if( k1 !=0  && k1 % 5000 == 0)
Sleep(10000);
if (connect(sClient[k1], (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("connect() failed: %d, faile number is:%d\n", WSAGetLastError(),k1);
Sleep(5000);
//同时释放前面的某个
closesocket(sClient[k1 - 1000]);
//return 1;
continue;
}
else
{
printf("connect() success: number is:%d-----------------------\n", k1);
//return 1;
continue;
}
}

(2)杀死一个client副本的操作方法我是通过直接点DOS黑窗口右上角的X来关闭
(3)另外我杀死client的时机正好也是client执行代码拼命不断的连接server的时候,但通过client代码大家也能看到,我client只是不断连接服务器并保持住连接不切断,但并不向服务器发送任何信息。

#5


经过跟踪这种AcceptEX实现方式的IOCP,AcceptEX的实现方式和传统的accept是不太一样的,我竟然发现当client端拼命发起多个连接来连接服务器的时候杀掉整个client端(任务管理器中直接杀进程),可能会造成服务器在AcceptEX处理之前连接上又断掉(这些连接请求会保存在Listen socket的连接请求队列中),这个时候我发现服务器端GetQueuedCompletionStatus函数会返回0,表失败,同时,我发现GetLastError()返回的是64错误,这个表示指定的网络名不再可用错误,这个一般来讲都正常,因为你client端突然断开,所有连接到server的连接会导致服务器端产生大量的GetQueuedCompletionStatus返回0的情况,但是:

奇怪的问题是,在这些GetQueuedCompletionStatus返回0的情况中,我居然发现了listen套接字的socket句柄也在其中(我改了下整个程序,从而绝不closesocket,保证listen套接字绝对不是因为服务器程序closesocket引起),当listen套接字的socket句柄在其中的时候,server端监听端口消失,client也就再也无法连接。
各位朋友分析到过这种情况没?

#6


难题解决,我理解错误。
GetQueuedCompletionStatus返回0,错误代码为64。
注意,我是每收到一个正常的ACCEPT请求后才在ACCEPT请求代码中再发起一个新的AcceptEx投递。

这里有个技术点,就是正常连接进来的socket会执行一系列ACCEPT请求代码(这些代码当然是由你写的),但若client拼命连接server,然后突然之间client端又被关闭,则服务器端会出现两种socket,这两种socket都是GetQueuedCompletionStatus返回0,错误代码为64的。
第一种就是已经正常连接进来的socket,这些正常连接进来的socket,我们只需要closesocket把他们关闭就行了,因为他们已经正常的执行了我的ACCEPT请求代码。

第二种就是“保存在Listen socket的连接请求队列中”的client socket,这些socket还没有来得及执行ACCEPT事件代码就被突然关闭的client端导致产生了GetQueuedCompletionStatus返回0,并且错误代码为64的错误,这种错误,我们的处理步骤是2个:
(1)关闭这个socket。
(2)发起新的AcceptEx请求以保证该IOCP线程可以收到新的连入请求。

#7


楼主的钻研精神令人佩服!学习了,

#8


结贴通知:
请lz注意结贴。。。。

#9


遇到相同的问题 学习了

#10


遇到相同的问题 学习了

#11


遇到相同的问题 学习了

#12


遇到相同的问题,感谢楼主给了个思路!