WSAWaitForMultipleEvents Function
The WSAWaitForMultipleEvents function returns when one or all of the specified event objects are in the signaled state, when the time-out interval expires, or when an I/O completion routine has executed.
Syntax
DWORD WSAWaitForMultipleEvents(
__in DWORD cEvents,
__in const WSAEVENT *lphEvents,
__in BOOL fWaitAll,
__in DWORD dwTimeout,
__in BOOL fAlertable
);
DWORD WSAWaitForMultipleEvents(
__in DWORD cEvents,
__in const WSAEVENT *lphEvents,
__in BOOL fWaitAll,
__in DWORD dwTimeout,
__in BOOL fAlertable
);
Parameters
cEvents [in]
The number of event object handles in the array pointed to by lphEvents. The maximum number of event object handles is WSA_MAXIMUM_WAIT_EVENTS. One or more events must be specified.
lphEvents [in]
A pointer to an array of event object handles. The array can contain handles of objects of different types. It may not contain multiple copies of the same handle if the fWaitAll parameter is set to TRUE. If one of these handles is closed while the wait is still pending, the behavior of WSAWaitForMultipleEvents is undefined. The handles must have the SYNCHRONIZE access right. For more information, see Standard Access Rights.
fWaitAll [in]
A value that specifies the wait type. If TRUE, the function returns when the state of all objects in the lphEvents array is signaled. If FALSE, the function returns when any of the event objects is signaled. In the latter case, the return value minus WSA_WAIT_EVENT_0 indicates the index of the event object whose state caused the function to return. If more than one event object became signaled during the call, this is the array index to the signaled event object with the smallest index value of all the signaled event objects.
dwTimeout [in]
The time-out interval, in milliseconds. WSAWaitForMultipleEvents returns if the time-out interval expires, even if conditions specified by the fWaitAll parameter are not satisfied. If the dwTimeout parameter is zero, WSAWaitForMultipleEvents tests the state of the specified event objects and returns immediately. If dwTimeout is WSA_INFINITE, WSAWaitForMultipleEvents waits forever; that is, the time-out interval never expires.
fAlertable [in]
A value that specifies whether the thread is placed in an alertable wait state so the system can execute I/O completion routines. If TRUE, the thread is placed in an altertable wait state and WSAWaitForMultipleEvents can return when the system executes an I/O completion routine. In this case, WSA_WAIT_IO_COMPLETION is returned and the event that was being waited on is not signaled yet. The application must call the WSAWaitForMultipleEvents function again. If FALSE, the thread is not placed in an altertable wait state and I/O completion routines are not executed.
Return Value
If the WSAWaitForMultipleEvents function succeeds, the return value upon success is one of the following values.
Return Value Meaning
WSA_WAIT_EVENT_0 to (WSA_WAIT_EVENT_0 + cEvents - 1) If the fWaitAll parameter is TRUE, the return value indicates that all specified event objects is signaled.
If the fWaitAll parameter is FALSE, the return value minus WSA_WAIT_EVENT_0 indicates the lphEvents array index of the signaled event object that satisfied the wait. If more than one event object became signaled during the call, the return value indicates the lphEvents array index of the signaled event object with the smallest index value of all the signaled event objects.
WSA_WAIT_IO_COMPLETION The wait was ended by one or more I/O completion routines that were executed. The event that was being waited on is not signaled yet. The application must call the WSAWaitForMultipleEvents function again. This return value can only be returned if the fAlertable parameter is TRUE.
WSA_WAIT_TIMEOUT The time-out interval elapsed and the conditions specified by the fWaitAll parameter were not satisfied. No I/O completion routines were executed.
If the WSAWaitForMultipleEvents function fails, the return value is WSA_WAIT_FAILED. The following table lists values that can be used with WSAGetLastError to get extended error information.
Error code Meaning
WSANOTINITIALISED A successful WSAStartup call must occur before using this function.
WSAENETDOWN The network subsystem has failed.
WSAEINPROGRESS A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.
WSA_NOT_ENOUGH_MEMORY Not enough free memory was available to complete the operation.
WSA_INVALID_HANDLE One or more of the values in the lphEvents array is not a valid event object handle.
WSA_INVALID_PARAMETER The cEvents parameter does not contain a valid handle count.
Remarks
The WSAWaitForMultipleEvents function determines whether the wait criteria have been met. If the criteria have not been met, the calling thread enters the wait state. It uses no processor time while waiting for the criteria to be met. The WSAWaitForMultipleEvents function returns when any one or all of the specified objects are in the signaled state, or when the time-out interval elapses.
When the bWaitAll parameter is TRUE, the wait operation is completed only when the states of all objects have been set to signaled. The function does not modify the states of the specified objects until the states of all objects have been set to signaled.
When bWaitAll parameter is FALSE, WSAWaitForMultipleEvents checks the handles in the lphEvents array in order starting with index 0, until one of the objects is signaled. If multiple objects become signaled, the function returns the index of the first handle in the lphEvents array whose object was signaled.
This function is also used to perform an alertable wait by setting the fAltertable parameter to TRUE. This enables the function to return when the system executes an I/O completion routine by the calling thread.
A thread must be in an alertable wait state in order for the system to execute I/O completion routines (asynchronous procedure calls or APCs). So if an application calls WSAWaitForMultipleEvents when there are pending asynchronous operations that have I/O completion routines and the fAlertable parameter is FALSE, then those I/O completion routines will not be executed even if those I/O operations are completed. If the fAlertable parameter is TRUE and one of the pending operations completes, the APC is executed and WSAWaitForMultipleEvents will return WSA_IO_COMPLETION. The pending event is not signaled yet. The application must call the WSAWaitForMultipleEvents function again.
Applications that require an alertable wait state without waiting for any event objects to be signaled should use the Windows SleepEx function.
The current implementation of WSAWaitForMultipleEvents calls the WaitForMultipleObjectsEx function.
Note Use caution when calling the WSAWaitForMultipleEvents with code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses WSAWaitForMultipleEvents with no time-out limit (the dwTimeout parameter set to WSA_INFINITE) may cause the system to become deadlocked.
Example Code
The following code example shows how to use the WSAWaitForMultipleEvents function.
以带有颜色区分的格式查看复制到剪贴板打印#include <windows.h>
#include <stdio.h>
#include "winsock2.h"
#define DATA_BUFSIZE 4096
void main() {
//-----------------------------------------
// Declare and initialize variables
WSABUF DataBuf;
char buffer[DATA_BUFSIZE];
DWORD EventTotal = 0,
RecvBytes = 0,
Flags = 0,
BytesTransferred = 0,
CallBack = 0;
WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
WSAOVERLAPPED AcceptOverlapped;
SOCKET ListenSocket, AcceptSocket;
//-----------------------------------------
// Initialize Winsock
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
//-----------------------------------------
// Create a listening socket bound to a local
// IP address and the port specified
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
u_short port = 27015;
char* ip;
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_port = htons(port);
hostent* thisHost;
thisHost = gethostbyname("");
ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);
service.sin_addr.s_addr = inet_addr(ip);
//-----------------------------------------
// Bind the listening socket to the local IP address
// and port number
bind(ListenSocket, (SOCKADDR *) &service, sizeof(SOCKADDR));
//-----------------------------------------
// Set the socket to listen for incoming
// connection requests
listen(ListenSocket, 1);
printf("Listening...\n");
//-----------------------------------------
// Accept and incoming connection request
AcceptSocket = accept(ListenSocket, NULL, NULL);
printf("Client Accepted...\n");
//-----------------------------------------
// Create an event handle and setup an overlapped structure.
EventArray[EventTotal] = WSACreateEvent();
ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));
AcceptOverlapped.hEvent = EventArray[EventTotal];
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
EventTotal++;
//-----------------------------------------
// Call WSARecv to receive data into DataBuf on
// the accepted socket in overlapped I/O mode
if (WSARecv(AcceptSocket, &DataBuf, 1, &RecvBytes, &Flags, &AcceptOverlapped, NULL) == SOCKET_ERROR) {
if (WSAGetLastError() != WSA_IO_PENDING)
printf("Error occurred at WSARecv()\n");
}
//-----------------------------------------
// Process overlapped receives on the socket
while (1) {
DWORD Index;
//-----------------------------------------
// Wait for the overlapped I/O call to complete
Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE);
//-----------------------------------------
// Reset the signaled event
WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
//-----------------------------------------
// Determine the status of the overlapped event
WSAGetOverlappedResult(AcceptSocket, &AcceptOverlapped, &BytesTransferred, FALSE, &Flags);
//-----------------------------------------
// If the connection has been closed, close the accepted socket
if (BytesTransferred == 0) {
printf("Closing Socket %d\n", AcceptSocket);
closesocket(AcceptSocket);
WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
return;
}
//-----------------------------------------
// If data has been received, echo the received data
// from DataBuf back to the client
if (WSASend(AcceptSocket, &DataBuf, 1, &RecvBytes, Flags, &AcceptOverlapped, NULL) == SOCKET_ERROR)
printf("WSASend() is busted\n");
//-----------------------------------------
// Reset the changed flags and overlapped structure
Flags = 0;
ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));
AcceptOverlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];
//-----------------------------------------
// Reset the data buffer
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
}
}
#include <windows.h>
#include <stdio.h>
#include "winsock2.h"
#define DATA_BUFSIZE 4096
void main() {
//-----------------------------------------
// Declare and initialize variables
WSABUF DataBuf;
char buffer[DATA_BUFSIZE];
DWORD EventTotal = 0,
RecvBytes = 0,
Flags = 0,
BytesTransferred = 0,
CallBack = 0;
WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
WSAOVERLAPPED AcceptOverlapped;
SOCKET ListenSocket, AcceptSocket;
//-----------------------------------------
// Initialize Winsock
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
//-----------------------------------------
// Create a listening socket bound to a local
// IP address and the port specified
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
u_short port = 27015;
char* ip;
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_port = htons(port);
hostent* thisHost;
thisHost = gethostbyname("");
ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);
service.sin_addr.s_addr = inet_addr(ip);
//-----------------------------------------
// Bind the listening socket to the local IP address
// and port number
bind(ListenSocket, (SOCKADDR *) &service, sizeof(SOCKADDR));
//-----------------------------------------
// Set the socket to listen for incoming
// connection requests
listen(ListenSocket, 1);
printf("Listening...\n");
//-----------------------------------------
// Accept and incoming connection request
AcceptSocket = accept(ListenSocket, NULL, NULL);
printf("Client Accepted...\n");
//-----------------------------------------
// Create an event handle and setup an overlapped structure.
EventArray[EventTotal] = WSACreateEvent();
ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));
AcceptOverlapped.hEvent = EventArray[EventTotal];
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
EventTotal++;
//-----------------------------------------
// Call WSARecv to receive data into DataBuf on
// the accepted socket in overlapped I/O mode
if (WSARecv(AcceptSocket, &DataBuf, 1, &RecvBytes, &Flags, &AcceptOverlapped, NULL) == SOCKET_ERROR) {
if (WSAGetLastError() != WSA_IO_PENDING)
printf("Error occurred at WSARecv()\n");
}
//-----------------------------------------
// Process overlapped receives on the socket
while (1) {
DWORD Index;
//-----------------------------------------
// Wait for the overlapped I/O call to complete
Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE);
//-----------------------------------------
// Reset the signaled event
WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
//-----------------------------------------
// Determine the status of the overlapped event
WSAGetOverlappedResult(AcceptSocket, &AcceptOverlapped, &BytesTransferred, FALSE, &Flags);
//-----------------------------------------
// If the connection has been closed, close the accepted socket
if (BytesTransferred == 0) {
printf("Closing Socket %d\n", AcceptSocket);
closesocket(AcceptSocket);
WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
return;
}
//-----------------------------------------
// If data has been received, echo the received data
// from DataBuf back to the client
if (WSASend(AcceptSocket, &DataBuf, 1, &RecvBytes, Flags, &AcceptOverlapped, NULL) == SOCKET_ERROR)
printf("WSASend() is busted\n");
//-----------------------------------------
// Reset the changed flags and overlapped structure
Flags = 0;
ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));
AcceptOverlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];
//-----------------------------------------
// Reset the data buffer
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
}
}
Requirements
Minimum supported client
Windows 2000 Professional
Minimum supported server
Windows 2000 Server
Header
Winsock2.h
Library
Ws2_32.lib
DLL
Ws2_32.dll
See Also
Standard Access Rights
WaitForMultipleObjectsEx
Winsock Reference
Winsock Functions
WSACloseEvent
WSACreateEvent
©
The WSAWaitForMultipleEvents function returns when one or all of the specified event objects are in the signaled state, when the time-out interval expires, or when an I/O completion routine has executed.
Syntax
DWORD WSAWaitForMultipleEvents(
__in DWORD cEvents,
__in const WSAEVENT *lphEvents,
__in BOOL fWaitAll,
__in DWORD dwTimeout,
__in BOOL fAlertable
);
DWORD WSAWaitForMultipleEvents(
__in DWORD cEvents,
__in const WSAEVENT *lphEvents,
__in BOOL fWaitAll,
__in DWORD dwTimeout,
__in BOOL fAlertable
);
Parameters
cEvents [in]
The number of event object handles in the array pointed to by lphEvents. The maximum number of event object handles is WSA_MAXIMUM_WAIT_EVENTS. One or more events must be specified.
lphEvents [in]
A pointer to an array of event object handles. The array can contain handles of objects of different types. It may not contain multiple copies of the same handle if the fWaitAll parameter is set to TRUE. If one of these handles is closed while the wait is still pending, the behavior of WSAWaitForMultipleEvents is undefined. The handles must have the SYNCHRONIZE access right. For more information, see Standard Access Rights.
fWaitAll [in]
A value that specifies the wait type. If TRUE, the function returns when the state of all objects in the lphEvents array is signaled. If FALSE, the function returns when any of the event objects is signaled. In the latter case, the return value minus WSA_WAIT_EVENT_0 indicates the index of the event object whose state caused the function to return. If more than one event object became signaled during the call, this is the array index to the signaled event object with the smallest index value of all the signaled event objects.
dwTimeout [in]
The time-out interval, in milliseconds. WSAWaitForMultipleEvents returns if the time-out interval expires, even if conditions specified by the fWaitAll parameter are not satisfied. If the dwTimeout parameter is zero, WSAWaitForMultipleEvents tests the state of the specified event objects and returns immediately. If dwTimeout is WSA_INFINITE, WSAWaitForMultipleEvents waits forever; that is, the time-out interval never expires.
fAlertable [in]
A value that specifies whether the thread is placed in an alertable wait state so the system can execute I/O completion routines. If TRUE, the thread is placed in an altertable wait state and WSAWaitForMultipleEvents can return when the system executes an I/O completion routine. In this case, WSA_WAIT_IO_COMPLETION is returned and the event that was being waited on is not signaled yet. The application must call the WSAWaitForMultipleEvents function again. If FALSE, the thread is not placed in an altertable wait state and I/O completion routines are not executed.
Return Value
If the WSAWaitForMultipleEvents function succeeds, the return value upon success is one of the following values.
Return Value Meaning
WSA_WAIT_EVENT_0 to (WSA_WAIT_EVENT_0 + cEvents - 1) If the fWaitAll parameter is TRUE, the return value indicates that all specified event objects is signaled.
If the fWaitAll parameter is FALSE, the return value minus WSA_WAIT_EVENT_0 indicates the lphEvents array index of the signaled event object that satisfied the wait. If more than one event object became signaled during the call, the return value indicates the lphEvents array index of the signaled event object with the smallest index value of all the signaled event objects.
WSA_WAIT_IO_COMPLETION The wait was ended by one or more I/O completion routines that were executed. The event that was being waited on is not signaled yet. The application must call the WSAWaitForMultipleEvents function again. This return value can only be returned if the fAlertable parameter is TRUE.
WSA_WAIT_TIMEOUT The time-out interval elapsed and the conditions specified by the fWaitAll parameter were not satisfied. No I/O completion routines were executed.
If the WSAWaitForMultipleEvents function fails, the return value is WSA_WAIT_FAILED. The following table lists values that can be used with WSAGetLastError to get extended error information.
Error code Meaning
WSANOTINITIALISED A successful WSAStartup call must occur before using this function.
WSAENETDOWN The network subsystem has failed.
WSAEINPROGRESS A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.
WSA_NOT_ENOUGH_MEMORY Not enough free memory was available to complete the operation.
WSA_INVALID_HANDLE One or more of the values in the lphEvents array is not a valid event object handle.
WSA_INVALID_PARAMETER The cEvents parameter does not contain a valid handle count.
Remarks
The WSAWaitForMultipleEvents function determines whether the wait criteria have been met. If the criteria have not been met, the calling thread enters the wait state. It uses no processor time while waiting for the criteria to be met. The WSAWaitForMultipleEvents function returns when any one or all of the specified objects are in the signaled state, or when the time-out interval elapses.
When the bWaitAll parameter is TRUE, the wait operation is completed only when the states of all objects have been set to signaled. The function does not modify the states of the specified objects until the states of all objects have been set to signaled.
When bWaitAll parameter is FALSE, WSAWaitForMultipleEvents checks the handles in the lphEvents array in order starting with index 0, until one of the objects is signaled. If multiple objects become signaled, the function returns the index of the first handle in the lphEvents array whose object was signaled.
This function is also used to perform an alertable wait by setting the fAltertable parameter to TRUE. This enables the function to return when the system executes an I/O completion routine by the calling thread.
A thread must be in an alertable wait state in order for the system to execute I/O completion routines (asynchronous procedure calls or APCs). So if an application calls WSAWaitForMultipleEvents when there are pending asynchronous operations that have I/O completion routines and the fAlertable parameter is FALSE, then those I/O completion routines will not be executed even if those I/O operations are completed. If the fAlertable parameter is TRUE and one of the pending operations completes, the APC is executed and WSAWaitForMultipleEvents will return WSA_IO_COMPLETION. The pending event is not signaled yet. The application must call the WSAWaitForMultipleEvents function again.
Applications that require an alertable wait state without waiting for any event objects to be signaled should use the Windows SleepEx function.
The current implementation of WSAWaitForMultipleEvents calls the WaitForMultipleObjectsEx function.
Note Use caution when calling the WSAWaitForMultipleEvents with code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses WSAWaitForMultipleEvents with no time-out limit (the dwTimeout parameter set to WSA_INFINITE) may cause the system to become deadlocked.
Example Code
The following code example shows how to use the WSAWaitForMultipleEvents function.
以带有颜色区分的格式查看复制到剪贴板打印#include <windows.h>
#include <stdio.h>
#include "winsock2.h"
#define DATA_BUFSIZE 4096
void main() {
//-----------------------------------------
// Declare and initialize variables
WSABUF DataBuf;
char buffer[DATA_BUFSIZE];
DWORD EventTotal = 0,
RecvBytes = 0,
Flags = 0,
BytesTransferred = 0,
CallBack = 0;
WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
WSAOVERLAPPED AcceptOverlapped;
SOCKET ListenSocket, AcceptSocket;
//-----------------------------------------
// Initialize Winsock
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
//-----------------------------------------
// Create a listening socket bound to a local
// IP address and the port specified
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
u_short port = 27015;
char* ip;
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_port = htons(port);
hostent* thisHost;
thisHost = gethostbyname("");
ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);
service.sin_addr.s_addr = inet_addr(ip);
//-----------------------------------------
// Bind the listening socket to the local IP address
// and port number
bind(ListenSocket, (SOCKADDR *) &service, sizeof(SOCKADDR));
//-----------------------------------------
// Set the socket to listen for incoming
// connection requests
listen(ListenSocket, 1);
printf("Listening...\n");
//-----------------------------------------
// Accept and incoming connection request
AcceptSocket = accept(ListenSocket, NULL, NULL);
printf("Client Accepted...\n");
//-----------------------------------------
// Create an event handle and setup an overlapped structure.
EventArray[EventTotal] = WSACreateEvent();
ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));
AcceptOverlapped.hEvent = EventArray[EventTotal];
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
EventTotal++;
//-----------------------------------------
// Call WSARecv to receive data into DataBuf on
// the accepted socket in overlapped I/O mode
if (WSARecv(AcceptSocket, &DataBuf, 1, &RecvBytes, &Flags, &AcceptOverlapped, NULL) == SOCKET_ERROR) {
if (WSAGetLastError() != WSA_IO_PENDING)
printf("Error occurred at WSARecv()\n");
}
//-----------------------------------------
// Process overlapped receives on the socket
while (1) {
DWORD Index;
//-----------------------------------------
// Wait for the overlapped I/O call to complete
Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE);
//-----------------------------------------
// Reset the signaled event
WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
//-----------------------------------------
// Determine the status of the overlapped event
WSAGetOverlappedResult(AcceptSocket, &AcceptOverlapped, &BytesTransferred, FALSE, &Flags);
//-----------------------------------------
// If the connection has been closed, close the accepted socket
if (BytesTransferred == 0) {
printf("Closing Socket %d\n", AcceptSocket);
closesocket(AcceptSocket);
WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
return;
}
//-----------------------------------------
// If data has been received, echo the received data
// from DataBuf back to the client
if (WSASend(AcceptSocket, &DataBuf, 1, &RecvBytes, Flags, &AcceptOverlapped, NULL) == SOCKET_ERROR)
printf("WSASend() is busted\n");
//-----------------------------------------
// Reset the changed flags and overlapped structure
Flags = 0;
ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));
AcceptOverlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];
//-----------------------------------------
// Reset the data buffer
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
}
}
#include <windows.h>
#include <stdio.h>
#include "winsock2.h"
#define DATA_BUFSIZE 4096
void main() {
//-----------------------------------------
// Declare and initialize variables
WSABUF DataBuf;
char buffer[DATA_BUFSIZE];
DWORD EventTotal = 0,
RecvBytes = 0,
Flags = 0,
BytesTransferred = 0,
CallBack = 0;
WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
WSAOVERLAPPED AcceptOverlapped;
SOCKET ListenSocket, AcceptSocket;
//-----------------------------------------
// Initialize Winsock
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
//-----------------------------------------
// Create a listening socket bound to a local
// IP address and the port specified
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
u_short port = 27015;
char* ip;
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_port = htons(port);
hostent* thisHost;
thisHost = gethostbyname("");
ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);
service.sin_addr.s_addr = inet_addr(ip);
//-----------------------------------------
// Bind the listening socket to the local IP address
// and port number
bind(ListenSocket, (SOCKADDR *) &service, sizeof(SOCKADDR));
//-----------------------------------------
// Set the socket to listen for incoming
// connection requests
listen(ListenSocket, 1);
printf("Listening...\n");
//-----------------------------------------
// Accept and incoming connection request
AcceptSocket = accept(ListenSocket, NULL, NULL);
printf("Client Accepted...\n");
//-----------------------------------------
// Create an event handle and setup an overlapped structure.
EventArray[EventTotal] = WSACreateEvent();
ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));
AcceptOverlapped.hEvent = EventArray[EventTotal];
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
EventTotal++;
//-----------------------------------------
// Call WSARecv to receive data into DataBuf on
// the accepted socket in overlapped I/O mode
if (WSARecv(AcceptSocket, &DataBuf, 1, &RecvBytes, &Flags, &AcceptOverlapped, NULL) == SOCKET_ERROR) {
if (WSAGetLastError() != WSA_IO_PENDING)
printf("Error occurred at WSARecv()\n");
}
//-----------------------------------------
// Process overlapped receives on the socket
while (1) {
DWORD Index;
//-----------------------------------------
// Wait for the overlapped I/O call to complete
Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE);
//-----------------------------------------
// Reset the signaled event
WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
//-----------------------------------------
// Determine the status of the overlapped event
WSAGetOverlappedResult(AcceptSocket, &AcceptOverlapped, &BytesTransferred, FALSE, &Flags);
//-----------------------------------------
// If the connection has been closed, close the accepted socket
if (BytesTransferred == 0) {
printf("Closing Socket %d\n", AcceptSocket);
closesocket(AcceptSocket);
WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
return;
}
//-----------------------------------------
// If data has been received, echo the received data
// from DataBuf back to the client
if (WSASend(AcceptSocket, &DataBuf, 1, &RecvBytes, Flags, &AcceptOverlapped, NULL) == SOCKET_ERROR)
printf("WSASend() is busted\n");
//-----------------------------------------
// Reset the changed flags and overlapped structure
Flags = 0;
ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));
AcceptOverlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];
//-----------------------------------------
// Reset the data buffer
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
}
}
Requirements
Minimum supported client
Windows 2000 Professional
Minimum supported server
Windows 2000 Server
Header
Winsock2.h
Library
Ws2_32.lib
DLL
Ws2_32.dll
See Also
Standard Access Rights
WaitForMultipleObjectsEx
Winsock Reference
Winsock Functions
WSACloseEvent
WSACreateEvent
©