Поделиться через


WSAPoll, A new Winsock API to simplify porting poll() applications to Winsock.

Hello, my name is Chad Carlin. I'm a software developer on the Winsock Test Team. Among the many improvements to the Winsock API shipping in Vista is the new WSAPoll function. Its primary purpose is to simplify the porting of a sockets application that currently uses poll() by providing an identical facility in Winsock for managing groups of sockets. Depending on the needs of your application, this addition could be an attractive option.

If you are new to poll, (since just about everyone is new to WSAPoll() ), I'll explain its role in network programming with a brief example. Suppose that you have a server application that is providing a service to several clients concurrently. You would not want your process to be blocked while waiting for a client to send or be able to receive data. You could create a thread per socket, but that would hinder the scalability of your application. By creating an array of structures, each with a member, which is a pointer to one of your sockets, you can poll this array to identify which sockets are guaranteed to be available for reading or writing data. This keeps your server process busy servicing ready clients or other performing useful work.

You should be aware that if you are choosing between using select() and WSAPoll(), that WSAPoll() scales better to a larger number of sockets and can accommodate sockets of different types. If you are creating a large-scale, high-performance Winsock2 application, we recommend that you use the native Winsock overlapped IO facilities.

If you have experience developing applications using poll(), WSAPoll will be very familiar. It is designed to behave just like poll(). In fact, I recently ported the Winsock WSAPoll SDK sample to run on BSD Unix. I know that sounds backwards from what you would expect but, we all like sample code after all. As it turns out it didn't matter which direction I ported. I had really hoped to have some clever insight to give you, or some real handy tip about how to work around some special difference. The truth is, the portions of the code dealing with poll() were unchanged from the sample. Except, of course, for changing the name of the API. Frankly, porting the poll() code went so smoothly, it made converting Windows threads to pthreads seem like the lion's share of the work.

To speed up your porting effort here are some tips:

The minimum set of include files that you'll need are: Winsock2.h, ws2tcpip.h and mstcpip.h. You'll want to switch from using the errno global variable to using the WSAGetLastError() function when looking for extended error codes.

For simplicity, the SDK sample uses macros to fill in the IPv6 address structures to connect or bind to the loopback interface. You should use getaddrinfo() which is the preferred method when writing an IP agnostic application. To support both address types you'll want to switch to using SOCKADDR_STORAGE types instead of sockaddr types used in BSD.

Here is an example of calling WSAPoll on a socket to check if it is writable. If the remote endpoint has accepted the connection, we call send. Get the full sample from the SDK for additional details.

 //Call poll for writeability on connecting socket
fdarray.fd = csock;
fdarray.events = POLLWRNORM;
if (SOCKET_ERROR == (ret = WSAPoll(&fdarray, 1, DEFAULT_WAIT )))
{
    ERR("poll");
}     
if (ret)
{
    if (fdarray.revents & POLLWRNORM)
    {
        printf("Established connection and signalled POLLWRNORM \n");            
        //Send data
        if (SOCKET_ERROR == (ret = send(csock, TST_MSG, sizeof (TST_MSG),)))
        {
            ERR("send");
        } else {
            printf("Sent %d bytes@ %d\n",ret, __LINE__);
        }
    }
... 

 

Listing of networking code samples in the Windows SDK:
https://windowssdk.msdn.microsoft.com/en-us/library/ms716684.aspx

Find the latest version of the Platform SDK which includes the sample mentioned above:
https://msdn.microsoft.com/downloads/

MSDN WSAPoll documentation page:
https://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/wsapoll.asp

--Chad Carlin

Comments

  • Anonymous
    November 11, 2006
    Actually on BSD and Linux you would use struct addrinfo, which is the preferred method to write ip-agnostic apps.  Use that instead of SOCKADDR_STORAGE if you can, then it will work on both platforms.

  • Anonymous
    November 14, 2006
    You forgot to mention that the socket must be in non-blocking mode before doing the I/O operation.

  • Anonymous
    November 14, 2006
    Thank you for your thoughtful comments. I just double checked that the SOCKADDR_STORAGE structure is isomorphic with the sockaddr structure. It's two benefits are that it is large enough to store v4 or v6 addresses and due to its padding will maintain 64-bit alignment. RFC 2553 at ietf.org has additional recommendations regarding its use. As a practical matter, I agree that you should put the socket in to non-blocking mode in case, for example, the size of the send exceeds available buffer space. In the sample shown above, WSAPoll guarantees that the call to send will not block.

  • Anonymous
    April 03, 2008
    It is not working on Windows XP + Visual Studio 5.0 as I tested. WSAPoll is Vista and higher (Server 2008)
    -- Ari

  • Anonymous
    July 29, 2008
    Can you please comment on the performance of WSAPoll vs select on win and WSAPoll vs poll on linux. I am seeing a perf issue where using select degrades performace by 40%. On linux the performace is almost the same with or without using the poll. Thx Select on Windows is mostly for compatibility not performance. If you are focused on performance and scalability there are better IO models to use. -- Ari

  • Anonymous
    October 13, 2008
    Any articles to point us to settings/config to get apps using the legacy winsock api to work in vista. Getting network errors unable to connect to host in vista.  Xp and older works fine.  But have not found a fix for this and a reset of the catalog does not help. Thanks Could this have to do with IPV6 being on by default in Vista? What's do you see in a netmon sniff? -- Ari

  • Anonymous
    November 29, 2008
    WSAPoll() vs select() performance - I would like to know the performance of WSAPoll() compared to select() on Windows. You see, porting between select() and WSAPoll() is not a major effort. With both functions you inquire before you act. Porting to IO completion is a MAJOR change in program design for my application. Here you do the IO action FIRST and then wait for notification that it has happened. If you say that WSAPoll() gives substantialy better peformance than select(), then I'll try it. If I know in advance then it will save me a lot of time. That WSAPoll does not work on Windows XP is a huge problem BTW. It means you can't create a portable EXE. Any way around this? Is Microsoft going to issue a service pack so XP guys can use this? This is one of thoose, write a little bit of code to see for yourself if it will help. Generally speaking, the best model is posting recv/sends with completion ports, so if you are going to change models, look at that first. I believe this api is there to help with porting of applications already on the poll model. To deal with backwards compatability, I generally attempt to dynamically load any function ptrs that might not be present at startup and then choose my implementation based on the api sets available. Good Luck. -- Ari

  • Anonymous
    August 19, 2009
    I'm coming in late to this discussion, but the quiet often the best thing to do if you are using c++ is to use the boost::asio networking library.  You program it in the style of IO Completion, and the program would work on all platforms regardless if it is internally using select, poll, epoll, or IO completion ports. --jeffk++

  • Anonymous
    May 02, 2011
    Hello, Could you advise on this ? social.msdn.microsoft.com/.../18769abd-fca0-4d3c-9884-1a38ce27ae90 We're bitten by this problem on our project, which makes WSAPoll completely useless. Are there known workarounds ? I'm thinking os putting an arbitrary timeout or going back to good old select (which doesn't look so buggy). Thanks, Aris

  • Anonymous
    October 04, 2012
    For Microsoft, it is a known issue: "Windows 8 Bugs 309411 - WSAPoll does not report failed connections  8/3/2011 6:53 PM Resolved as Won't Fix by muraris  Has been like this forever and people are already used to it." "The recommendation for now is to not use the WSAPoll function it in case you encounter this issue, but rather the other Net-API functions." See curl.haxx.se/.../0038.html for further discussion.