WinSock重なりI/Oモデル


//   
/*
。     7-8  ,                
      ,         ,      ,              。     
          :

①        ,        ,         。

②            。

③            WSAOVERLAPPED   。

④            WSARecv   ,    WSAOVERLAPPED       ,    
      。

⑤   fAlertable     TRUE     ,  WSAWaitForMultipleEvents,      
 I/O     。       ,         ,  WSAWaitForMultipleEvents     
 WSA_IO_COMPLETION。      ,          ,       WSARecv   。

⑥   WSAWaitForMultipleEvents     WSA_IO_COMPLETION。
⑦    ⑤   ⑥ 。

    7-8            I/O     
//   :           I/O               ,         
   ,

  */
//                    。     5150           TCP  
// ,
//            ,                  



//   :cl -o overlap overlap.cpp ws2_32.lib
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>


#pragma comment(lib,"ws2_32.lib") 

#define PORT 5150
#define DATA_BUFSIZE 8192


typedef struct _SOCKET_INFORMATION {
	CHAR Buffer[DATA_BUFSIZE];   
	WSABUF DataBuf;
	SOCKET Socket;
	WSAOVERLAPPED Overlapped;
	DWORD BytesSEND;
	DWORD BytesRECV;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;




DWORD EventTotal = 0;   //      

DWORD WINAPI ProcessIO(LPVOID lpParameter);

WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];

LPSOCKET_INFORMATION SocketArray[WSA_MAXIMUM_WAIT_EVENTS];   

CRITICAL_SECTION CriticalSection;


int main(void)
{
	WSADATA wsaData;

	SOCKET ListenSocket, AcceptSocket;

	SOCKADDR_IN InternetAddr;

	DWORD Flags;

	DWORD ThreadId;

	DWORD RecvBytes;

	INT Ret;

	InitializeCriticalSection(&CriticalSection);   //      

	printf("       
") ; if ((Ret = WSAStartup(0x0202,&wsaData)) != 0) { printf("WSAStartup failed with error %d
", Ret); WSACleanup(); return 0 ; } if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) // { printf("Failed to get a socket %d
", WSAGetLastError()); return 0 ; } InternetAddr.sin_family = AF_INET; InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY); InternetAddr.sin_port = htons(PORT); if (bind(ListenSocket, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR) // { printf("bind() failed with error %d
", WSAGetLastError()); return 0 ; } if (listen(ListenSocket, 5)) { printf("listen() failed with error %d
", WSAGetLastError()); return 0 ; } // if ((AcceptSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) // { printf("Failed to get a socket %d
", WSAGetLastError()); return 0 ; } if ((EventArray[0] = WSACreateEvent()) == WSA_INVALID_EVENT) // { printf("WSACreateEvent failed with error %d
", WSAGetLastError()); return 0 ; } // printf("
") ; if (CreateThread(NULL, 0, ProcessIO, NULL, 0, &ThreadId) == NULL) // ThreadIO, ProcessIO ? { printf("CreateThread failed with error %d
", GetLastError()); return 0 ; } EventTotal = 1; // int i = 0 ; while(TRUE) { // printf("Main %d
",i+1) ; i++ ; printf(" ,
") ; if ((AcceptSocket = accept(ListenSocket, NULL, NULL)) == INVALID_SOCKET) { printf("accept failed with error %d
", WSAGetLastError()); return 0 ; } EnterCriticalSection(&CriticalSection); // ?? // if ((SocketArray[EventTotal] = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR, sizeof(SOCKET_INFORMATION))) == NULL) { printf("GlobalAlloc() failed with error %d
", GetLastError()); return 0 ; } // SocketArray[EventTotal]->Socket = AcceptSocket; // ? ZeroMemory(&(SocketArray[EventTotal]->Overlapped), sizeof(OVERLAPPED)); SocketArray[EventTotal]->BytesSEND = 0; SocketArray[EventTotal]->BytesRECV = 0; SocketArray[EventTotal]->DataBuf.len = DATA_BUFSIZE; SocketArray[EventTotal]->DataBuf.buf = SocketArray[EventTotal]->Buffer; if ((SocketArray[EventTotal]->Overlapped.hEvent = EventArray[EventTotal] = WSACreateEvent()) == WSA_INVALID_EVENT) // { printf("WSACreateEvent() failed with error %d
", WSAGetLastError()); return 0; } // WSARecv Flags = 0; if (WSARecv(SocketArray[EventTotal]->Socket, &(SocketArray[EventTotal]->DataBuf), 1, &RecvBytes, &Flags, &(SocketArray[EventTotal]->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed with error %d
", WSAGetLastError()); return 0; } } EventTotal++; printf("
") ; LeaveCriticalSection(&CriticalSection); // , if (WSASetEvent(EventArray[0]) == FALSE) { printf("WSASetEvent failed with error %d
", WSAGetLastError()); return 0 ; } }//while return 0 ; } DWORD WINAPI ProcessIO(LPVOID lpParameter) { DWORD Index; DWORD Flags; LPSOCKET_INFORMATION SI; DWORD BytesTransferred; DWORD i; DWORD RecvBytes, SendBytes; printf(" ProcessIO
") ; int j = 0 ; // WSASend、WSARecv while(TRUE) { printf("ProcessIO %d
",j+1) ; j++ ; if ((Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED) { printf("WSAWaitForMultipleEvents failed %d
", WSAGetLastError()); return 0; } // , if ((Index - WSA_WAIT_EVENT_0) == 0) // 0 , ? ? { WSAResetEvent(EventArray[0]); continue; } SI = SocketArray[Index - WSA_WAIT_EVENT_0]; WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]); if (WSAGetOverlappedResult(SI->Socket, &(SI->Overlapped), &BytesTransferred, FALSE, &Flags) == FALSE || BytesTransferred == 0) { printf("Closing socket %d
", SI->Socket); if (closesocket(SI->Socket) == SOCKET_ERROR) { printf("closesocket() failed with error %d
", WSAGetLastError()); } GlobalFree(SI); WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]); // SocketArray EventArray EnterCriticalSection(&CriticalSection); // 。。 if ((Index - WSA_WAIT_EVENT_0) + 1 != EventTotal) for (i = Index - WSA_WAIT_EVENT_0; i < EventTotal; i++) { EventArray[i] = EventArray[i + 1]; SocketArray[i] = SocketArray[i + 1]; } EventTotal--; LeaveCriticalSection(&CriticalSection); // continue; } // BytesRECV 0, WSARecv , // // WSARecv BytesTransferred BytesRECV if (SI->BytesRECV == 0) { SI->BytesRECV = BytesTransferred; SI->BytesSEND = 0; } else { SI->BytesSEND += BytesTransferred; } if (SI->BytesRECV > SI->BytesSEND) { // WSASend() , WSASend() , // // WSASend() ZeroMemory(&(SI->Overlapped), sizeof(WSAOVERLAPPED)); SI->Overlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0]; SI->DataBuf.buf = SI->Buffer + SI->BytesSEND; SI->DataBuf.len = SI->BytesRECV - SI->BytesSEND; if (WSASend(SI->Socket, &(SI->DataBuf), 1, &SendBytes, 0, &(SI->Overlapped), NULL) == SOCKET_ERROR) // { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSASend() failed with error %d
", WSAGetLastError()); return 0; } } } else { SI->BytesRECV = 0; // WSARecv Flags = 0; ZeroMemory(&(SI->Overlapped), sizeof(WSAOVERLAPPED)); SI->Overlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0]; SI->DataBuf.len = DATA_BUFSIZE; SI->DataBuf.buf = SI->Buffer; if (WSARecv(SI->Socket, &(SI->DataBuf), 1, &RecvBytes, &Flags, &(SI->Overlapped), NULL) == SOCKET_ERROR) // { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed with error %d
", WSAGetLastError()); return 0; } } else { // printf(" : %s",SI->DataBuf ) ; } } } printf(" ProcessIO
") ; }
 
 
 


//   
/*

    6-2       ,          ,               ,  
        。      ,          。        ,        
       。                。
               TCP        。                 
 ,            。  ,      ,       。  ,        
   ,                。     ,             TCP   
     ,   ,            ,     ,             , 
       。           ,            -O     。  ,   
       ,         。

		  
			
       :
server -p:5150 -o
        :
client -p:5150 -s:IP -n:10 -o
               10  send   ,          recv    ,  
  10    。


*/



//    6-2        


//   :     ,  TCP    ,    ,           
//     :cl -o Client Client.c ws2_32.lib
//
//      :
// client [-p:x] [-s:IP] [-n:x] [-o]
// -p:x        
// -s:IP    IP       
// -n:x       
// -o      ,   
//

#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>

#pragma  comment(lib, "Ws2_32.lib ")

#define DEFAULT_COUNT 10

#define DEFAULT_PORT 5150

#define DEFAULT_BUFFER 2048

#define DEFAULT_MESSAGE "This is a test of the emergency \
broadcasting system"


char szServer[128], //       

szMessage[1024]; //          

int iPort = DEFAULT_PORT; //          

DWORD dwCount = DEFAULT_COUNT; //       

BOOL bSendOnly = FALSE; //      ,   


 void usage() ;
 void ValidateArgs(int argc, char **argv) ;

//   :main
//   :     ,   Winsock,       ,     ,     ,    
//  
//    
int main(int argc, char **argv)
{
	WSADATA wsd;
	SOCKET sClient;
	char szBuffer[DEFAULT_BUFFER];
	int ret,i;

	struct sockaddr_in server;

	struct hostent *host = NULL;

	//          Winsock
	ValidateArgs(argc, argv);

	if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
	{
		printf("Failed to load Winsock library!
"); return 1; } strcpy(szMessage, DEFAULT_MESSAGE); // , sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sClient == INVALID_SOCKET) { printf("socket() failed: %d
", WSAGetLastError()); return 1; } server.sin_family = AF_INET; server.sin_port = htons(iPort); server.sin_addr.s_addr = inet_addr(szServer); // "aaa.bbb.ccc.ddd", , if (server.sin_addr.s_addr == INADDR_NONE) { host = gethostbyname(szServer); if (host == NULL) { printf("Unable to resolve server: %s
", szServer); return 1; } CopyMemory(&server.sin_addr, host->h_addr_list[0], host->h_length); } if (connect(sClient, (struct sockaddr *)&server,sizeof(server)) == SOCKET_ERROR) { printf("connect() failed: %d
", WSAGetLastError()); return 1; } // for(i = 0; i < dwCount; i++) { ret = send(sClient, szMessage, strlen(szMessage), 0); if (ret == 0) break; else if (ret == SOCKET_ERROR) { printf("send() failed: %d
", WSAGetLastError()); break; } printf("Send %d bytes
", ret); if (!bSendOnly) { ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0); if (ret == 0) // Graceful close break; else if (ret == SOCKET_ERROR) { printf("recv() failed: %d
", WSAGetLastError()); break; } szBuffer[ret] = '\0'; printf("RECV [%d bytes]: '%s'
", ret, szBuffer); } } closesocket(sClient); WSACleanup(); return 0; } void usage() { printf("usage: client [-p:x] [-s:IP] [-n:x] [-o]

"); printf(" -p:x Remote port to send to
"); printf(" -s:IP Server's IP address or hostname
"); printf(" -n:x Number of times to send message
"); printf(" -o Send messages only; don't receive
"); ExitProcess(1); } // :ValidateArgs // : , void ValidateArgs(int argc, char **argv) { int i; for(i = 1; i < argc; i++) { if ((argv[i][0] == '-') || (argv[i][0] == '/')) { switch (tolower(argv[i][1])) { case 'p': // Remote port if (strlen(argv[i]) > 3) iPort = atoi(&argv[i][3]); break; case 's': // Server if (strlen(argv[i]) > 3) strcpy(szServer, &argv[i][3]); break; case 'n': // Number of times to send message if (strlen(argv[i]) > 3) dwCount = atol(&argv[i][3]); break; case 'o': // Only send message; don't receive bSendOnly = TRUE; break; default: usage(); break; } } } }