Вы находитесь на странице: 1из 17

o -

IOCP IOCP

/ , " completion port. , , /

"

. I/O ,

, ( , www.microsoft.com), . Windows NT, Windows 2000, Windows XP , . , " CreateIoCompletionPort(), ( ( . I/O , . , . CreateIoCompletionPort(), : I/O 4.5.1.1) MSDN,

Windows Server 2003 . , 16 -

". )

I/O,

HANDLE CreateIoCompletionPort ( HANDLE FileHandle, HANDLE ExistingCompletionPort, DWORD CompletionKey, DWORD NumberOfConcurrentThreads );
, : 1. 2. , . . - NumberOfConcurrentThreads; NumberOfConcurrentThreads , , , ,

, . , I/O: CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL, 0, 0); , , . , 0 .

, . , . ? , . ; , . , ,

, , , ,

CreateIoCompletionPort() . CreateIoCompletionPort() CreateIoCompletionPort() n . , n , n .

NumberOfConcurrentThreads

( ,

, CreateIoCompletionPort().) , , , . CreateIoCompletionPort()?

proxy"

"

Sleep() . . .

WaitForSingleObject())

NumberOfConcurrentThreads, NumberOfConcurrentThread / . FileHandle, ExistingCompletionPort . FileHandle . , ,

. . , CreateIoCompletionPort()

CompletionKey ,

ExistingCompletionPort . "per -handle data", CompletionKey

. , "per-handle data" , " , , / , , / : 1. . . 2. 3. , , , , , 4. 5150. 5. 6. 7. , data" 8. , ( 5 8, , . , CreateIoCompletionPort(). CreateIoCompletionPort() I/O / ( . . ), . . accept(). "per -handle data" accept(), "per-handle . , WSASend() ). , , CreateThread(), . . , 2. , . I/O 0 . ECHO. . LIFO. , , , . , , , , . , " , " ". , . , .

. WSARec() .

DWORD WINAPI ServerThread (LPVOID CompletionPortID);// HANDLE CompletionPort; // WSADATA wsd; // SYSTEM_INFO SystemInfo; // SOCKADDR_IN InternetAddr; // SOCKET Listen_socket; int i; WSADATA

typedef struct _PER_HANDLE_DATA { SOCKET Accept_socket; // SOCKADDR_STORAGE ClientAddr; // // , } PER_HANDLE_DATA, * LPPER_HANDLE_DATA; // WinSock StartWinsock(MAKEWORD(2,2), &wsd); // 1: // CompletionPort = CreateIoCompletionPort (INVALID_HANDLE_VALUE, NULL, 0, 0); // 2: // , GetSystemInfo(&SystemInfo); // 3: // , , // . // . for(i = 0; i < SystemInfo.dwNumberOfProcessors ; i++) { HANDLE ThreadHandle; // , . // : ServerWorkerThread() . ThreadHandle = CreateThread (NULL, 0,ServerWorkerThread, CompletionPort,0, &ThreadId); // CloseHandle(ThreadHandle); } // 4: // ( WSA_FLAG_OVERLAPPED) Listen_socket = WSASocket (AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); InternetAddr.sin_family = AF_INET; InternetAddr.sin_addr.s_addr = htonl (INADDR_ANY); InternetAddr.sin_port = htons (5150); bind(Listen, (PSOCKADDR) &InternetAddr,sizeof(InternetAddr)); // listen(Listen_socket, 5); while(TRUE) { PER_HANDLE_DATA *PerHandleData=NULL; SOCKADDR_IN saRemote; SOCKET Accept_socket; int RemoteLen; // 5: // RemoteLen = sizeof(saRemote); Accept_socket = WSAAccept (Listen_socket, (SOCKADDR

*)&saRemote,&RemoteLen); // 6: //

" per -handle data",

PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA)); printf("Socket number %d connected \n", Accept_socket); PerHandleData->Socket = Accept_socket; memcpy(&PerHandleData->ClientAddr, &saRemote, RemoteLen ); // 7: // CreateIoCompletionPort ((HANDLE)Accept_socket,CompletionPort, (DWO RD) PerHandleData,0); // 8: // / . // WSASend() WSARecv() // I/O. // WSARecv() / WSASend() // , SOCKET_ERROR // WSA_IO_PENDING, // ). } DWORD WINAPI ServerWorkerThread (LPVOID lpParam) { ..... return 0; }
/ , , . . . I/O. GetQueuedCompletionStatus(), , ,

BOOL GetQueuedCompletionStatus ( HANDLE CompletionPort, // the I/O completion port of interest LPDWORD lpNumberOfBytesTransferred, // to receive number of bytes // transferred during I/O LPDWORD lpCompletionKey, // to receive file's completion key LPOVERLAPPED *lpOverlapped, // to receive pointer to OVERLAPPED structure DWORD dwMilliseconds // optional timeout value );

: CompletionPort lpNumberOfBytesTransferred WSASend/WSARecv lpCompletionKey lpOverlapped dwMilliseconds ) FALSE OVERLAPPED(INFINITE , dwMilliseconds =0 . . *lpOverlapped NULL , ERROR_SUCCESS, 0. , ( , ). Per-I/O , , . , Per -I/O: , OVERLAPPED. OVERLAPPED , ECHO / , OVERLAPPED, , , 0. , GetLastError() WAIT_TIMEOUT. , , GetQueuedCompletionStatus() *lpOverlapped -NULL lpNumberOfBytes lpOverlapped Per -I/O, OVERLAPPED, ,

* lpOverlapped ,

NULL.

typedef struct { OVERLAPPED Overlapped; // : WSABUF DataBuf; CHAR Buffer[DATA_BUFSIZE]; DWORD BytesSend; DWORD BytesRecv; DWORD OperationType; DWORD TotalBytes; ..... } PER_IO_OPERATION_DATA;
, / , , , OVERLAPPED / , ,

. WinSock OVERLAPPED . : PER_IO_OPERATION_DATA PerIoData; ... WSARecv(socket, &wbuf, 1, &Bytes, &Flags, &(PerIoData.Overla pped),NULL); GetQueuedCompletionStatus() . CONTAINING_RECORD. per -

I/O :

PER_IO_DATA *PerIoData=NULL; OVERLAPPED *lpOverlapped=NULL; ret = GetQueuedCompletionStatus(CompPortHandle,&Transferred, (PULONG_PTR)&CompletionKey,&lpOverlapped,INFINITE); PerIoData = CONTAINING_RECORD(lpOverlapped, PER_IO_DATA, Overlapped); PER_IO_DATA , , , , , . ECHO ServerWorkerThread(): . . I/O , PerIoData . , . OVERLAPPED ,

DWORD WINAPI ServerWorkerThread (LPVOID CompletionPortID) { HANDLE CompletionPort = (HANDLE) CompletionPortID; DWORD BytesTransferred; LPOVERLAPPED Overlapped; LPPER_HANDLE_DATA PerHandleData; LPPER_IO_DATA PerIoData; DWORD SendBytes, RecvBytes; DWORD Flags; while(TRUE) { // / , // if (GetQueuedCompletionStatus (CompletionPort, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0) { // . printf ("GetQueuedCompletionStatus failed with error %d \n", GetLastError ()); return 0; } // BytesTransferred=0, // , // if (BytesTransferred == 0 &&(PerIoData->OperationType == RECV_POSTED PerIoData->OperationType == SEND_POSTED )) { closesocket(PerHandleData->Socket); GlobalFree(PerHandleData); ,

GlobalFree(PerIoData); continue;// } // . , // OperationTypefield if (PerIoData->OperationType == RECV_POSTED) { // WSARecv(), // } // // , WSASend() WSARecv(). PerIoData ->Buffer

PerIoData

WSARecv()

Flags = 0; // ZeroMemory(&(PerIoData->Overlapped),sizeof(OVERLAPPED)); PerIoData->DataBuf.len = DATA_BUFSIZE; PerIoData->DataBuf.buf = PerIoData->Buffer; PerIoData->OperationType = RECV_POSTED; // WSARecv() WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL); }//End While }//End ServerWorkerThread()
. GetQueuedCompletionStatus() Windows, WinSock WSAGetOverlappedResult() WSAOVERLAPPED, WinSock. , FALSE. GetLastError(). , WSAGetLastError() - . . " " PER_IO_OPERATION_DATA ,

. OperationType :

switch { case // ... case // ... case //

(PerIoData->OperationType) SRV_NEW_CONNECTION: : SRV_DATA_SEND: SRV_DATA_RECV:

... case SRV_DISCONNECT: // ....... }


OVERLAPPED, , , , PostQueuedCompletionStatus(), : closesocket() . .

BOOL PostQueuedCompletionStatus ( HANDLE CompletionPort,

//

DWORD dwNumberOfBytesTransferred, // GetQueuedCompletionStatus() DWORD dwCompletionKey, // GetQueuedCompletionStatus() LPOVERLAPPED lpOverlapped // GetQueuedCompletionStatus() );


CompletionPort , , GetQueuedCompletionStatus() , , Etc...

, ,

GetQueuedCompletionStatus() . 0 dwCompletionKey , . CloseHandle() . ,

o IOCP
#include <stdio.h> #include <conio.h> #include <malloc.h> #include <winsock2.h> #pragma comment (lib,"ws2_32.lib") #define PORT 28912 // DWORD WINAPI ClientPool (SOCKET client);

//

//-------------------------------------------------------------------------void main(void){

int j; // WORD wVersionRequested; // WSADATA wsaData; // int err; // char address[16]={0}; // ( ) char buffer[128]; // SOCKET sd; // HANDLE hThread; // DWORD ThreadId; // // ws2_32.dll wVersionRequested=MAKEWORD (2,2); err=WSAStartup(wVersionRequested,&wsaData ); if(err==SOCKET_ERROR){ strcpy(buffer," WSAStartup "); CharToOem(buffer,buffer); printf("%s %d\n",buffer, WSAGetLastError ()); WSACleanup(); // getch(); return; } strcpy(buffer," " ); CharToOem(buffer,buffer); printf("%s\n",buffer); scanf("%s",address); // C sd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP ); if(sd==INVALID_SOCKET){ strcpy(buffer," socket "); CharToOem(buffer,buffer); printf("%s %d\n",buffer, WSAGetLastError ()); WSACleanup(); // getch(); return; } SOCKADDR_IN sin;// ZeroMemory(&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(PORT); sin.sin_addr.s_addr =inet_addr (address); if(connect(sd, (PSOCKADDR)&sin, sizeof(SOCKADDR))==-1) { strcpy(buffer," " ); CharToOem(buffer,buffer); printf("%s %d\n",buffer, GetLastError()); WSACleanup(); // getch(); return; } strcpy(buffer," " ); CharToOem(buffer,buffer); printf("%s\n",buffer); // ClientPool()

hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE )ClientPool,(void*)sd , 0, &ThreadId); while(true) { scanf("%s",buffer); if(strcmp(buffer,"EXIT")==0) { TerminateThread(hThread,0); if (sd!=INVALID_SOCKET)closesocket(sd); // break; } send(sd,buffer,strlen(buffer),0); } WSACleanup(); // return; } //-------------------------------------------------------------------------// //-------------------------------------------------------------------------DWORD WINAPI ClientPool (SOCKET client) { int bytes; char buffer[128]; while(true) { bytes=recv(client,buffer,sizeof(buffer),0); buffer[strlen(buffer)]='\0'; if(strlen(buffer)!=0)printf("%s\n",buffer); } return 0; }

#include <stdio.h> #include <conio.h> #include <malloc.h> #include <Winsock2.h> #include <list> // #pragma comment (lib,"ws2_32.lib") ws2_32.lib using namespace std; std #define BUFF_SIZE 1024 // #define PORT 28912 // DWORD WINAPI ServerPool(HANDLE hp); void SendToAll(char *buffer,unsigned //

IOCP

STL // //

long bytes);

//

SOCKET server_sock; // int ClientCount; // list <SOCKET> ClientList; // //-------------------------------------------------------------------------struct ovpConnection: public OVERLAPPED { int client_number; // SOCKET c; // char * buffer; // enum { op_type_send, // op_type_recv // }op_type; // }; //-------------------------------------------------------------------------void main(int argc, char *argv[]) { int err; // char buffer[128]; // WORD wVersionRequested; // WSADATA wsaData; // HANDLE hCp; // LPOVERLAPPED overlapped; // I/O HANDLE hThread; // DWORD ThreadId; // DWORD flags; // WSARecv // ws2_32.dll wVersionRequested=MAKEWORD (2,2); err=WSAStartup(wVersionRequested,&wsaData ); if(err==SOCKET_ERROR) { strcpy(buffer," WSAStartup"); CharToOem(buffer,buffer); printf("%s %d\n",buffer, WSAGetLastError()); WSACleanup(); // getch(); return; } // hCp=CreateIoCompletionPort (INVALID_HANDLE_VALUE,NULL, 0,0); if(hCp==NULL) { strcpy(buffer," CreateIoCompletionPort" ); CharToOem(buffer,buffer); printf("%s %d\n",buffer, GetLastError()); WSACleanup(); // getch(); return; }

// server_sock=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,NULL, WSA_FLAG_OVERLAPPED); if(server_sock==INVALID_SOCKET ) { strcpy(buffer," WSASocket"); CharToOem(buffer,buffer); printf("%s %d\n",buffer, WSAGetLastError()); WSACleanup(); // getch(); return; } else { // if(CreateIoCompletionPort ((HANDLE)server_sock,hCp,0,0)==NULL) { strcpy(buffer," CreateIoCompletionPort" ); CharToOem(buffer,buffer); printf("%s %d\n",buffer, GetLastError()); WSACleanup(); // getch(); return; } } // SOCKADDR_IN sinServer; sinServer.sin_family = AF_INET; sinServer.sin_port = htons (PORT); sinServer.sin_addr.s_addr = INADDR_ANY; err = bind( server_sock,(LPSOCKADDR)&sinServer,sizeof(sinServer) ); if(err==-1) { strcpy(buffer," bind"); CharToOem(buffer,buffer); printf("%s %d\n",buffer, GetLastError()); WSACleanup(); // getch(); return; } // err = listen(server_sock, SOMAXCONN ); if(err==-1) { strcpy(buffer," listen "); CharToOem(buffer,buffer); printf("%s %d\n",buffer, GetLastError()); WSACleanup(); //

getch(); return; } //C hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ServerPool,hCp,0, &ThreadId); ClientCount=0; strcpy(buffer," \n"); CharToOem(buffer,buffer); printf("%s",buffer); // while(true) { // SOCKADDR_IN sinClient; int lenClient=sizeof(sinClient); SOCKET client = accept(server_sock,(struct sockaddr*)&sinClient, &lenClient); CreateIoCompletionPort((HANDLE)client,hCp,0,0); // ClientList.insert(ClientList.end(),client); // overlappedovpConnection * op = new ovpConnection; // overlappedop->sock_handle = client; op->op_type = ovpConnection::op_type_recv; op->buffer = new char[BUFF_SIZE]; op->hEvent = 0; op->client_number=++ClientCount; strcpy(buffer," %d , %d\n"); CharToOem(buffer,buffer); printf(buffer,ClientCount,ClientList.size ()); unsigned long b; WSABUF buf; buf.buf = op->buffer; buf.len = BUFF_SIZE; flags=0; err=WSARecv(op->sock_handle, &buf, 1, &b, &flags, op, 0); if(!err) { strcpy(buffer," WSARecv"); CharToOem(buffer,buffer); printf("%s %d\n",buffer, WSAGetLastError ()); } } return; } //--------------------------------------------------------------

------------// //-------------------------------------------------------------------------DWORD WINAPI ServerPool(HANDLE hp) { int err; // unsigned long bytes; // unsigned long key; // , char buffer[128]; // LPOVERLAPPED overlapped; // I/O HANDLE hport=hp; // DWORD flags; // WSARecv() while(true) { // if(GetQueuedCompletionStatus (hport, &bytes, &key, &overlapped, INFINITE)) { // ovpConnection * op = (ovpConnection*)overlapped; // switch(op->op_type) { // case ovpConnection::op_type_send: delete [] op->buffer; delete op; break; // case ovpConnection::op_type_recv: if(!bytes) { // ClientList.remove(op->sock_handle); closesocket(op->sock_handle); strcpy(buffer," %d , %d\n"); CharToOem(buffer,buffer); printf(buffer,op->client_number,ClientList.size ()); break; } op->buffer[bytes]='\0'; if(op->buffer[0]=='*') // , // { strcpy(buffer," %s\n"); CharToOem(buffer,buffer); %d * -

} else { if(!overlapped) { // // , , for(list<SOCKET>::iterator i=ClientList.begin();i!=ClientList.end();i++) { closesocket(*i); } ClientList.clear(); closesocket(server_sock); CloseHandle(hport); strcpy(buffer," %d, \n"); CharToOem(buffer,buffer); printf(buffer,GetLastError()); getch(); exit(0); } else { // closesocket(((ovpConnection*)overlapped)->sock_handle); ClientList.remove(((ovpConnection*)overlapped)>sock_handle); strcpy(buffer," %d , %d\n"); CharToOem(buffer,buffer);

printf(buffer,op->client_number,(op->buffer+1)); SendToAll(op->buffer, bytes); // } else { strcpy(buffer," %d %s \n"); CharToOem(buffer,buffer); printf(buffer,op->client_number,op->buffer); } unsigned long b; WSABUF buf; buf.buf = op->buffer; buf.len = BUFF_SIZE; // buffer_len err=WSARecv(op->sock_handle, &buf, 1, &b, &flags, op, 0); if(!err) { strcpy(buffer," WSARecv"); CharToOem(buffer,buffer); printf("%s %d\n",buffer, WSAGetLastError ()); } }

printf(buffer,((ovpConnection*)overlapped)->client_number, ClientList.size()); } } } return 0; } //-------------------------------------------------------------------------// //-------------------------------------------------------------------------void SendToAll(char *buffer,unsigned long bytes) { // for(list<SOCKET>::iterator i=ClientList.begin();i!=ClientList.end();i++) { ovpConnection * op = new ovpConnection; op->sock_handle = *i; op->op_type = ovpConnection::op_type_send; op->buffer = new char[bytes-1]; memcpy(op->buffer, (buffer+1), bytes-1); op->buffer[bytes-1]='\0'; unsigned long b; WSABUF buf; buf.buf = op->buffer; buf.len = BUFF_SIZE; WSASend(op->sock_handle,&buf,1,&b, 0, op, 0); } return; }

Вам также может понравиться