简体   繁体   English

在WinSock中处理异步套接字?

[英]Handling asynchronous sockets in WinSock?

I'm using a message window and WSAAsyncSelect. 我正在使用消息窗口和WSAAsyncSelect。 How can I keep track of multiple sockets (the clients) with one message window? 如何通过一个消息窗口跟踪多个套接字(客户端)?

Windows Supports several modes of socket operation, and you do need to be clear which one you are using: Windows支持多种套接字操作模式,您需要清楚使用哪种模式:

  • Blocking sockets. 阻塞套接字。 send and recv block. 发送和recv块。
  • Non-Blocking sockets: send and recv return E_WOULDBLOCK, and select() is used to determine which sockets are ready 非阻塞套接字:send和recv返回E_WOULDBLOCK,select()用于确定哪些套接字已准备就绪
  • Asynchronous sockets: WSAAsyncSelect - sockets post event notifications to an HWND. 异步套接字:WSAAsyncSelect - 套接字将事件通知发送到HWND。
  • EventSockets: WSAEventSelect - sockets signal events. EventSockets:WSAEventSelect - 套接字信号事件。
  • Overlapped Sockets: WSASend and WSARecv are used with sockets by passing in the OVERLAPPED structures. 重叠套接字:WSASend和WSARecv通过传入OVERLAPPED结构与套接字一起使用。 Overlapped Sockets can be combined with IOCompletionPorts and provide the best scalability. 重叠套接字可与IOCompletionPorts结合使用,并提供最佳可扩展性。

In terms of convenience, asynchronous sockets are simple, and supported by MFC CAsyncSocket class. 在方便性方面,异步套接字很简单,并且由MFC CAsyncSocket类支持。

Event Sockets are tricky to use as the maximum number of objects passable to WaitForMultipleObjects is 64. 事件套接字很难使用,因为可传递给WaitForMultipleObjects的最大对象数为64。

Overlapped sockets, with IO CompletionPorts, is the most scalable way to handle sockets and allows windows based servers to scale to tens of thousands of sockets. 具有IO CompletionPorts的重叠套接字是处理套接字的最可扩展方式,并允许基于Windows的服务器扩展到数万个套接字。


In my experience, when using Async Sockets, the following things come to mind: 根据我的经验,在使用Async Sockets时,会想到以下几点:

  • Handling FD events via window messages can handle "lots" of sockets, but performance will begin to suffer as all the event handling is done in one thread, serialized through a message queue that might be busy handling UI events too if used in a single threaded GUI app. 通过窗口消息处理FD事件可以处理“很多”套接字,但是性能将开始受到影响,因为所有事件处理都在一个线程中完成,通过消息队列进行序列化,如果在单个线程中使用,也可能忙于处理UI事件GUI应用程序。

  • If you are hosting GUI windows or timers on the same thread as lots of sockets: WM_TIMER and WM_PAINT messages are low priority, and will only be generated if the message queue is empty. 如果您在与许多套接字相同的线程上托管GUI窗口或计时器:WM_TIMER和WM_PAINT消息是低优先级的,并且只有在消息队列为空时才会生成。 Very busy sockets can thus cause GUI painting, or SetTimer based timing to fail. 非常繁忙的套接字因此可能导致GUI绘制或基于SetTimer的定时失败。

  • Creating a dedicated worker thread to handle your sockets if hosting a GUI solves these problems. 如果托管GUI可以创建专用的工作线程来处理套接字,从而解决了这些问题。 Given that the worker thread will have a message loop, you can use the message queue for inter-thread comms - just post WM_APP messages to the thread. 鉴于工作线程将具有消息循环,您可以将消息队列用于线程间通信 - 只需将WM_APP消息发布到线程。

  • The easiest way to map FD callbacks to your socket objects is to create an Array of SocketObjects for each HWND that will be receiving messages, and then use WM_USER+index as the message ID each time you call WASAsyncSelect. 将FD回调映射到套接字对象的最简单方法是为每个将接收消息的HWND创建一个SocketObjects数组,然后在每次调用WASAsyncSelect时使用WM_USER + index作为消息ID。 Then, when you receive messages in the range WM_USER to WM_USER+(array size) you can quickly extract the corresponding state object. 然后,当您收到WM_USER到WM_USER +(数组大小)范围内的消息时,您可以快速提取相应的状态对象。 WM_USER is 0x400, and WM_APP is 0x8000, so you can index up to 31744 sockets per message window using this method. WM_USER为0x400,WM_APP为0x8000,因此您可以使用此方法为每个消息窗口索引最多31744个套接字。

  • Don't use a static scope array. 不要使用静态范围数组。 You need to associate the array with the window as you might want to create sockets on multiple threads. 您需要将数组与窗口关联,因为您可能希望在多个线程上创建套接字。 Each thread will need its own message loop, and message window. 每个线程都需要自己的消息循环和消息窗口。

  • HWND_MESSAGE is your friend HWND_MESSAGE是你的朋友

The wParam parameter of the window message that you tell WSAAsyncSelect() to send will specify the socket that triggered the message. 您告诉WSAAsyncSelect()发送的窗口消息的wParam参数将指定触发消息的套接字。 This is clearly stated in the WSAAsyncSelect() documentation : 这在WSAAsyncSelect() 文档中有明确说明:

When one of the nominated network events occurs on the specified socket s, the application window hWnd receives message wMsg. 当指定的套接字s上发生一个指定的网络事件时,应用程序窗口hWnd接收消息wMsg。 The wParam parameter identifies the socket on which a network event has occurred. wParam参数标识发生网络事件的套接字。 The low word of lParam specifies the network event that has occurred. lParam的低位字指定已发生的网络事件。 The high word of lParam contains any error code. lParam的高位字包含任何错误代码。 The error code be any error as defined in Winsock2.h. 错误代码是Winsock2.h中定义的任何错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM