Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets WSASocket编程,如何将非阻塞connect()函数保留到某个时间点?_Sockets - Fatal编程技术网

Sockets WSASocket编程,如何将非阻塞connect()函数保留到某个时间点?

Sockets WSASocket编程,如何将非阻塞connect()函数保留到某个时间点?,sockets,Sockets,我在WSASocket编程中遇到问题。我想在服务器端做一些技巧,这样 它可以让客户端在WSAWaitForEvents()函数中等待一段时间 FD_连接事件 详情如下: 在客户端,套接字是非阻塞模式。它尝试连接到服务器。它的主代码类似于: SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); WSAEvent hEvent = WSACreateEvent(); WSAEventSelect(s, hEvent, FD_CONNECT);

我在WSASocket编程中遇到问题。我想在服务器端做一些技巧,这样 它可以让客户端在WSAWaitForEvents()函数中等待一段时间 FD_连接事件

详情如下:

  • 在客户端,套接字是非阻塞模式。它尝试连接到服务器。它的主代码类似于:

    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    WSAEvent hEvent = WSACreateEvent();
    
    WSAEventSelect(s, hEvent, FD_CONNECT); //this also make socket non-blocking mode.
    
    connect(s, &someserveraddr, sizeof(someserveraddr)); //connect to some server in non-block mode
    
    WSAWaitForMultipleEvents(1, &hEvent, TRUE, WSA_INFINITE, FALSE); //this will block until success or faile
    
  • 在服务器端,当服务器看到来自该客户端的连接时,它将执行一些特殊的操作,这也需要一些时间,例如:调用doSomethingLengthy(),因此我希望在函数WSAWaitForMultipleEvents(…)处保留客户端阻塞,直到服务器完成该任务。但我不知道如何做到这一点。通常,服务器代码如下所示:

    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    
    bind(s, &someaddress, sizeof(someaddress));
    
    listen(s, 5);
    
    SOCKET acceptSocket = accept(s, &someotheraddress, sizeof(someotheraddress));
    

  • 问题是,我不知道在哪里/何时调用doSomethingLengthy()。我知道,完成listen()后,将通知客户端完成,WSAWaitForMultipleEvents()将返回。但是我不能在listen()之前调用doSomethingLengthy(),否则客户端连接()将失败。

    您不能。连接的服务器端在服务器通过待办事项队列查看已接受的套接字之前发生。

    FD\u connect
    告诉您套接字何时已连接,但
    FD\u WRITE
    告诉您何时允许通过连接发送数据。因此,请尝试等待
    FD\u WRITE
    (请注意,在连接的生命周期内,您可以多次获得
    FD\u WRITE
    ,但在成功的
    connect()
    之后,除了
    FD\u connect
    )之外,您将始终获得它。

    如果服务器不需要查看接受的套接字,该怎么办,它将为所有接受的套接字调用doSomethingLengthy()?可能吗?关键是操作系统在后台建立连接,并将其放入队列中,以便
    accept()
    从中拉出。即使您不调用
    accept()
    connect()
    也可能成功。
    doSomethingLengthy()
    到底在做什么,每个客户端是否真的需要调用它?您可以预先调用它,甚至在并行线程中调用它,并缓存结果以备需要时使用吗?在不知道您实际想要完成什么的情况下回答您的问题是非常困难的。而且,无论您延迟客户机的原因是什么,您为什么要浪费线程在服务器上的时间来延迟客户机呢?套接字中继实现中使用了这种逻辑。一旦服务器看到来自客户端的连接,服务器还需要建立到另一台服务器的另一个连接,这将需要一些时间,因为我们在第二秒钟使用块模式。因此,我们希望服务器保持第一个连接,直到第二个后台连接完成(失败或成功)。如果出站连接失败,您所能做的就是重置入站连接,除非您可以通过代理协议告诉客户端一些事情(如果有)。在任何情况下,您都不需要
    doSomethingLengthy():
    出站阻塞连接将完成您需要的所有阻塞。确定。另一方面,什么会导致connect()函数在被阻塞一段时间后成功?我的意思是,连接要么立即成功(在服务器正在侦听的情况下),要么超时(在服务器上未侦听的情况下,或者防火墙被阻止或其他情况下,这将被视为失败)。但是在什么情况下,connect()会在被阻塞一段时间后返回OK?因为服务器和客户端之间的距离太长?我看不出这有什么帮助
    FD_CONNECT
    和第一个
    FD_WRITE
    应同时交付。它们并不是真正不同的事件:它们都意味着套接字发送缓冲区已出现,以响应连接完成。我对其进行了测试,确信这两个事件都在未调用
    accept()
    的情况下发生。在服务器完全接受套接字之前,我希望它是不可写的。哦,那它怎么知道呢?TCP没有告诉它这种情况。首先,我希望操作系统会延迟三方握手。即使它延迟了,也没有,仍然没有TCP协议交换告诉它服务器的accept()已返回,而不是连接握手已完成,即无法区分FD_connect和FD_WRITE。