如何在Windows中退出阻塞connect()调用?
有没有办法退出Windows中的阻塞如何在Windows中退出阻塞connect()调用?,c,sockets,winapi,winsock,C,Sockets,Winapi,Winsock,有没有办法退出Windows中的阻塞connect()调用 请注意,我不想切换到非阻塞套接字。根据MSDN: 注意发出阻塞Winsock调用(如connect)时,Winsock可能需要等待网络事件,然后才能完成调用。在这种情况下,Winsock会执行可警报的等待,这可能会被安排在同一线程上的异步过程调用(APC)中断。在中断同一线程上正在进行的阻塞Winsock调用的APC内发出另一个阻塞Winsock调用将导致未定义的行为,Winsock客户端决不能尝试 因此,如果要取消connect调用,
connect()
调用
请注意,我不想切换到非阻塞套接字。根据MSDN:
注意发出阻塞Winsock调用(如connect)时,Winsock可能需要等待网络事件,然后才能完成调用。在这种情况下,Winsock会执行可警报的等待,这可能会被安排在同一线程上的异步过程调用(APC)中断。在中断同一线程上正在进行的阻塞Winsock调用的APC内发出另一个阻塞Winsock调用将导致未定义的行为,Winsock客户端决不能尝试
因此,如果要取消connect
调用,必须从另一个线程执行:
/* apc callback */
VOID CALLBACK apc( _In_ ULONG_PTR data)
{
/* warning, some synchronization should be added here*/
printf("connect canceled by APC\n");
}
/* second thread code */
DWORD WINAPI cancel_thread_function(void* main_thread_handle)
{
/* wait 500 ms*/
Sleep(500);
if (test_if_connect_is_still_pending())
{
/* cancel connect */
QueueUserAPC(apc, (HANDLE)main_thread_handle, (ULONG_PTR) NULL);
}
return 0;
}
/* The thread in which is executed the connect call */
HANDLE mainThread;
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &mainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
/* create cancelation thread */
CreateThread(NULL, 0, cancel_thread_function, , 0, NULL);
/* Warning: I should close the handles... */
connect(...);
在我看来,EJP解决方案是最好的(非阻塞
connect
并使用select
进行测试)。不是答案,因为我这里没有参考资料,但我模糊地记得这是不可能的。也许CancelIoEx
能满足您的需求吗?查看为什么不使用?您可以从单独的线程关闭套接字,或者在非阻塞模式下进行连接,然后在成功后切换回阻塞模式,并使用select()
轮询完成。或者等待连接超时,大约一分钟。@Steve您不需要将所有内容都更改为非阻塞。只需在调用connect()
之前将套接字置于非阻塞模式,然后在连接完成后将其置于阻塞模式。APC方法的缺点是它有竞争条件。在线程认为connect()
仍处于挂起状态后,connect()
可能会退出,并且其调用线程会在实际看到排队的APC之前继续移动,因此它将留在队列中,并可能在将来中断其他内容。因此,在退出connect()
后,如果线程仍在运行,则必须取消该线程,等待它实际终止,如果APC仍在队列中,则必须将其从队列中移除。