Overlapped I/O ¸ðµ¨
ÃÑ ÆäÀÌÁö ¼ö : 3224

Àüü ÇÔ¼ö/¿ë¾î»çÀü
Facebook Joinc ±×·ì   Joinc QA »çÀÌÆ®



joinc´Â Firefox¿Í chrome¿¡¼­ Å×½ºÆ® Çß½À´Ï´Ù. IE¿¡¼­´Â Å×À̺íÀÌ ±úÁö°Å³ª À̹ÌÁö°¡ º¸ÀÌÁö ¾ÊÀ» ¼ö ÀÖ½À´Ï´Ù. ƯÈ÷ ±¸±Û DocsÀ̹ÌÁöÀÇ °æ¿ì ¿¢¹Úó¸®µÉ ¼ö ÀÖ½À´Ï´Ù.

Contents

1 Overlapped I/O ¸ðµ¨
1.1 Overlapped ¼ÒÄÏ ÇÁ·Î±×·¥
1.1.1 À̺¥Æ® °´Ã¼ ±â¹Ý ó¸®
1.1.2 Äݹé ÇÔ¼ö È£Ãâ

1 Overlapped I/O ¸ðµ¨

¼ÒÄÏÀº ±âº»ÀûÀ¸·Î ºÀ¼â/µ¿±â·Î ¸¸µé¾îÁø´Ù. ÀÌ ¸ðµ¨Àº µ¥ÀÌÅÍ ÀÔÃâ·Â ºÎºÐ¿¡¼­ ºÀ¼â(blocked)µÈ´Ù´Â ¹®Á¦Á¡À» °¡Áø´Ù.


ÀÌ ¸ðµ¨·Î´Â ÇϳªÀÇ ¾²·¹µå¿¡¼­ µÎ °³ ÀÌ»óÀÇ ¼ÒÄÏÀ» ´Ù·ç±â°¡ Èûµé´Ù. ÀÌ ¸ðµ¨À» ¹Ù²ÙÁö ¾Ê°í µÎ°³ ÀÌ»óÀÇ ¼ÒÄÏÀ» ó¸®ÇÏ·Á¸é "¸ÖƼ ¾²·¹µå" ±â¼úÀ» ÇÔ²² »ç¿ëÇÏ´Â ¼ö ¹Û¿¡ ¾ø´Ù.

À©µµ ¿î¿µÃ¼Á¦´Â ¸ÖƼ ŽºÅ·À» Áö¿øÇÑ´Ù. ÀÌ´Â ÀÔÃâ·Â ¸ðµ¨°ú´Â »ó°ü¾øÀÌ, Ä¿³ÎÀº ¿©·¯ ¼ÒÄÏÀ¸·Î ºÎÅÍÀÇ ÀÔ·ÂÀ» ó¸®ÇÑ´Ù´Â Àǹ̴Ù. À̱â´ÉÀ» ºÀ¼â/µ¿±â ÀÔÃâ·Â ¸ðµ¨ÀÇ ÇѰè·Î ¾²Áö ¸øÇÏ´Â °ÍÀÏ »ÓÀÌ´Ù.

ÀÌ ¹®Á¦´Â ÀÔÃâ·Â ¸ðµ¨À» "ºñµ¿±â / ºÀ¼â" ȤÀº "ºñµ¿±â / ºñºÀ¼â"À» ¾²´Â °ÍÀ¸·Î ÇØ°áÇÒ ¼ö ÀÖ´Ù. ºñµ¿±â ºÀ¼â ¸ðµ¨À» »ç¿ëÇÏ´Â ±â¼úÀÌ selectÇÔ¼ö¸¦ ÀÌ¿ëÇÑ ÀÔÃâ·Â ´ÙÁßÈ­ÀÌ´Ù. Overlapped I/O ¸ðµ¨Àº "ºñµ¿±â / ºñºÀ¼â ¸ðµ¨"ÀÇ ÀÀ¿ë ¸ðµ¨ÀÌ´Ù. Overlapped¿¡´Â non-blockingÀÌ Æ÷ÇԵǾî ÀÖ´Ù. Áï Overlapped ´Â non-block + (ºñµ¿±âÀû) ¿Ï·á Å뺸 ¶ó°í º¸¸é µÈ´Ù.

Overlapped I/O´Â ´ÙÀ½°ú °°ÀÌ ¹¦»çÇÒ ¼ö ÀÖ´Ù. (Á¤È®ÇÑ ¹¦»ê´Â ¾Æ´Ï´Ù.)


¾Õ¼­ ¾ð±ÞÇßµíÀÌ Ä¿³ÎÀº ¿©·¯ °³ÀÇ ¼ÒÄÏÀÇ µ¥ÀÌÅ͸¦ µ¿½Ã¿¡ ´Ù·ê ¼ö ÀÖ´Ù. ±×·¯´Ù º¸¸é ½Ã°£À» ÃàÀ¸·Î µ¥ÀÌÅͰ¡ ÁßøÀÌ µÇ´Â ±¸°£ÀÌ »ý±æ ¼öµµ ÀÖÀ» °ÍÀÌ´Ù. ÀÌÁ¦ µ¥ÀÌÅÍÀÇ ÀÔ·ÂÀÌ ¿Ï·áµÇ¸é, ÇØ´ç ¼ÒÄÏ¿¡¼­ À̺¥Æ®¸¦ ÅëÁöÇÑ´Ù. À̺¥Æ®¸¦ ¹ÞÀº ÇÁ·Î¼¼½º´Â À̺¥Æ® °´Ã¼¸¦ ÀÌ¿ëÇØ¼­ µ¥ÀÌÅ͸¦ ó¸®Çϰųª ȤÀº Completion Routine¸¦ ÀÌ¿ëÇØ¼­ µ¥ÀÌÅ͸¦ ó¸®ÇÒ ¼ö ÀÖ´Ù. ÁßÃ¸ÇØ¼­ µé¾î¿Ã ¼ö ÀÖ´Â µ¥ÀÌÅÍÀÇ Ã³¸®¸¦ Ä¿³Î¿¡ ¸Ã±â°Ô µÇ¹Ç·Î À¯Àú ¸ðµå¿¡¼­ ºí·°µÇ´Â ÀÏ ¾øÀÌ ¿©·¯ °³ÀÇ ¼ÒÄÏÀ» ó¸®ÇÒ ¼ö ÀÖ´Ù.

Overlapped I/OÀÇ ÁßøÀ» Çã¿ëÇÏ´Â ÀÌ·± Ư¡ ¶§¹®¿¡, "Áßø ÀÔÃâ·Â ¸ðµ¨"À̶ó°í ºÎ¸£±âµµ ÇÑ´Ù. »ý¼ÒÇÑ ±â¼ú °°Áö¸¸, ¿ø¸®¿¡ À־´Â ¸®´ª½ºÀÇ ÀÔÃâ·Â ´ÙÁßÈ­³ª ¸®¾ó ŸÀÓ ½Ã±×³Î°ú Å« Â÷À̰¡ ¾øÀ½À» ¾Ë ¼ö ÀÖ´Ù. ´ÙÀ½Àº ºñ µ¿±â / ºñ ºÀ¼â ÀÔÃâ·Â¸ðµ¨À» µû¸£´Â ÇÁ·Î±×·¥ÀÇ È帧À» º¸¿©ÁØ´Ù.
  1. Àбâ ÇÔ¼ö¸¦ È£ÃâÇϸé, Ä¿³ÎÀº µ¥ÀÌÅ͸¦ Àбâ À§ÇÑ ÃʱâÈ­ ÀÛ¾÷À» ÇÏ°í µ¥ÀÌÅ͸¦ ±â´Ù¸°´Ù. Àбâ ÇÔ¼ö´Â ¹Ù·Î ¹ÝȯÇÑ´Ù.
  2. ÀÌÁ¦ ÇÁ·Î±×·¥Àº ´Ù¸¥ ÀÛ¾÷À» ÁøÇàÇÑ´Ù.
  3. µ¥ÀÌÅͰ¡ ÀԷµǸé, À̺¥Æ®°¡ ¹ß»ýÇÑ´Ù.
  4. ÇÁ·Î±×·¥Àº ÄݹéÇÔ¼ö ȤÀº À̺¥Æ® °´Ã¼¸¦ ¸¸µé¾î¼­ µ¥ÀÌÅ͸¦ Àо ó¸®ÇÑ´Ù.

ÇÏÁö¸¸ ¸®´ª½ºÀÇ ÀÔÃâ·Â ´ÙÁßÈ­³ª ¸®¾ó ŸÀÓ ½Ã±×³Îµî ºñµ¿±â ÀÔÃâ·Â ±â¼ú°ú Â÷ÀÌÁ¡ÀÌ ÀÖ´Ù. ÀÌµé ¸®´ª½º ¸ðµ¨Àº µ¥ÀÌÅÍ ÀÔ·ÂÀÌ ¿Ï·áµÈ ½ÃÁ¡¿¡¼­ µ¥ÀÌÅ͸¦ Àд ¹æ½ÄÀÌ ¾Æ´Ï´Ù. ¼ÒÄÏÀ¸·Î µ¥ÀÌÅͰ¡ ÀԷµǴ ½ÃÁ¡¿¡¼­ Ä¿³Î µ¥ÀÌÅ͸¦ À¯Àú µ¥ÀÌÅÍ·Î º¹»çÇÑ´Ù. À̸»Àº Ä¿³Î·Î ºÎÅÍ µ¥ÀÌÅÍÀÇ º¹»ç°¡ ³¡³¯ ¶§±îÁö ¸î ¹øÀ̳ª ÀÔÃâ·Â ÇÔ¼ö¸¦ È£Ãâ ÇÒ ¼öµµ ÀÖÀ½À» ÀǹÌÇÑ´Ù. ¿©·¯ ¹ø À¯Àú ¸ðµå¿Í Ä¿³Î ¸ðµå°£ÀÇ º¯È¯ÀÌ ÀÖÀ¸¹Ç·Î ¼º´ÉÀÌ °¨¼ÒÇÒ ¼ö ¹Û¿¡ ¾ø´Ù.

À©µµÀÇ Overlapped I/O¸ðµ¨Àº µ¥ÀÌÅÍ ÀÔÃâ·ÂÀÌ ¿Ï·áµÈ ½ÃÁ¡¿¡¼­ À̺¥Æ®¸¦ ¹ß»ýÇÑ´Ù. ÀÌ·Î ÀÎÇØ ¾òÀ» ¼ö ÀÖ´Â ÀÌÁ¡Àº ´ÙÀ½°ú °°´Ù.
  1. ¸ðµå º¯È¯ÀÌ ¹ß»ýÇÏÁö ¾Ê´Â´Ù. (¿©·¯ ¹øÀÇ µ¥ÀÌÅÍ º¹»ç°¡ ¹ß»ýÇÏÁö ¾Ê´Â´Ù.)
  2. µ¥ÀÌÅÍ ÀÔÃâ·ÂÀÌ ÁøÇàµÇ´Â µ¿¾È¿¡µµ ´Ù¸¥ ÀÏÀ» ÇÒ ¼ö ÀÖ´Ù.

1.1 Overlapped ¼ÒÄÏ ÇÁ·Î±×·¥

socket ÇÔ¼ö·Î ¸¸µç ¼ÒÄÏÀº ±âº»ÀûÀ¸·Î Áßø Ư¼ºÀ» °¡Áø´Ù. ±×·¯³ª ´Ù¸¥ BSD ¼ÒÄÏÀÔÃâ·Â ÇÔ¼öµé·Î´Â Áßø ¼ÒÄÏÀ» ´Ù·çÁö ¸øÇÑ´Ù. ±×·¯¹Ç·Î BSD ¼ÒÄÏ ÀÔÃâ·Â ÇÔ¼ö´ë½Å WSASend, WSARecv, WSASendTo, WSARecvFrom µîÀÇ ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¾ß ÇÑ´Ù. WSASocket ÇÔ¼ö·Î ¼ÒÄÏÀ» ¸¸µé °æ¿ì¿¡´Â WSA_FLAG_OVERLAPPED¸¦ ÁöÁ¤ÇØÁà¾ß ÇÑ´Ù.

Áßø ¼ÒÄÏÀ» »ç¿ëÀº WSAsend ÇÔ¼öÀÇ lpOverlapped ¸Å°³ º¯¼ö¿Í lpCompletionRoutine ¸Å°³ º¯¼ö·Î ÀÌ·ç¾îÁø´Ù.
  1. lpOverlapped : WSAOVERLAPPED±¸Á¶Ã¼ÀÇ Æ÷ÀÎÅ͸¦ ³Ñ±ä´Ù. ¸¸¾à NULL À̶ó¸é Áßø ¼ÒÄÏ Æ¯¼ºÀ» »ç¿ëÇÏÁö ¾Ê´Â´Ù.
  2. lpCompletionRoutine : ÀÔ·ÂÀÌ ¿Ï·á µÇ¾úÀ» ¶§ È£ÃâÇÒ ¿Ï·á ·çƾÀ» ¼³Á¤ÇÑ´Ù. ¸¸¾à NULL À̶ó¸é, À̺¥Æ® °´Ã¼ ±â¹ÝÀ¸·Î ó¸®ÇÑ´Ù.

1.1.1 À̺¥Æ® °´Ã¼ ±â¹Ý ó¸®

lpCompletionRoutineÀÌ NULLÀÏ °æ¿ì, WSAOVERLAPPED ±¸Á¶Ã¼ÀÇ À̺¥Æ® °´Ã¼ Çڵ鷯·Î ÀÔ·ÂÀ» ó¸®ÇÑ´Ù. À̶§ acceptÇÔ¼ö¸¦ ¾î¶»°Ô ó¸®ÇØ¾ß ÇÒ °ÍÀ̳« ÇÏ´Â ¹®Á¦°¡ ÀÖ´Ù. accept ÇÔ¼ö´Â Áßø ¼ÒÄÏ Æ¯¼ºÀ» ÀÌ¿ëÇÏÁö ¸øÇÑ´Ù. ¶ÇÇÑ WSAAccept ÇÔ¼öµµ Áßø ¼ÒÄÏ Æ¯¼ºÀ» ÀÌ¿ëÇÏÁö ¸øÇÑ´Ù. accept´Â ´Ü 1 ¹ÙÀÌÆ®¸¸ µé¾î¿Íµµ ¿äûÀÌ ¿Ï·áµÇ¹Ç·Î, ±»ÀÌ Áßø Ư¼ºÀ» ÀÌ¿ëÇÒ Çʿ䰡 ¾ø±â ¶§¹®ÀÌ´Ù. acceptEx ÇÔ¼ö°¡ ÀÖ±â´Â ÇÏÁö¸¸, ±×´ÙÁö ¾²°í ½ÍÁö ¾Ê´Ù.

´ÙÀ½ µÎ °¡Áö ¹æ¹ý Áß Çϳª¸¦ ¼±ÅÃÇÏ¸é µÉ °Í °°´Ù.
  1. ¸ÖƼ ¾²·¹µå ÇÁ·Î±×·¡¹Ö
    accept´Â ¸ÞÀÎ ¾²·¹µå¿¡¼­ ó¸®Çϰí, ÀÔÃâ·ÂÀº ¿öÄ¿ ¾²·¹µå¿¡¼­ ó¸®Çϵµ·Ï ÇÑ´Ù. µÎ °³ÀÇ ¾²·¹µå°¡ ÇÊ¿äÇÏ´Ù.
  2. WSAEventSelect ¸ðµ¨À» ÀÌ¿ëÇØ¼­ ó¸®ÇÑ´Ù.

À̺¥Æ® °´Ã¼ ±â¹Ý ó¸® ¿¹Á¦. ¸ÖƼ ¾²·¹µå¸¦ ÀÌ¿ëÇØ¼­ accept 󸮸¦ ºÐ¸® Çß´Ù.
#include <winsock2.h> 
#include <windows.h> 
#include <stdio.h> 
  
#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; 
 
// ¿¬°á ¼ÒÄÏ (inbound connection)À¸·Î ÀÔÃâ·Â 󸮸¦ À§ÇÑ ¾²·¹µå ÇÔ¼ö 
DWORD WINAPI ProcessIO(LPVOID lpParameter); 
  
DWORD EventTotal = 0; 
 
// À̺¥Æ® ÀúÀåÀ» À§ÇÑ ±¸Á¶Ã¼ ¹è¿­°ú 
// ¼ÒÄÏ Á¤º¸¸¦ ÀúÀåÇϱâ À§ÇÑ ±¸Á¶Ã¼ ¹è¿­ 
WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS]; 
LPSOCKET_INFORMATION SocketArray[WSA_MAXIMUM_WAIT_EVENTS]; 
 
// ÀÓ°è ¿µ¿ª ¼³Á¤À» À§ÇÑ Å©¸®Æ¼Äà ¼½¼Ç °´Ã¼ 
// EventArray, SocketArray ¿¬»ê ¿µ¿ªÀ» ÀÓ°è ¿µ¿ªÀ¸·Î ÁöÁ¤Çϱâ À§Çؼ­ »ç¿ëÇÑ´Ù. 
CRITICAL_SECTION CriticalSection; 
  
int main(int argc, char **argv) 
{ 
   WSADATA wsaData; 
   SOCKET ListenSocket, AcceptSocket; 
   SOCKADDR_IN InternetAddr; 
   DWORD Flags; 
   DWORD ThreadId; 
   DWORD RecvBytes; 
  
   InitializeCriticalSection(&CriticalSection); 
  
   if (WSAStartup((2,2),&wsaData) != 0) 
   { 
      printf("WSAStartup() failed with error %d\n", WSAGetLastError()); 
      WSACleanup(); 
      return 1; 
   } 
   else 
     printf("WSAStartup() looks nice!\n"); 
  
   if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) 
   { 
      printf("Failed to get a socket %d\n", WSAGetLastError()); 
      return 1; 
   } 
   else 
      printf("WSASocket() is OK lol!\n"); 
  
   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\n", WSAGetLastError()); 
      return 1; 
   } 
   else 
      printf("YOu see, bind() is working!\n"); 
  
   if (listen(ListenSocket, 5)) 
   { 
      printf("listen() failed with error %d\n", WSAGetLastError()); 
      return 1; 
   } 
   else 
      printf("listen() is OK maa...\n"); 
  
   // Áßø ¼ÒÄÏ »ý¼º  
   if ((AcceptSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) 
   { 
      printf("Failed to get a socket %d\n", WSAGetLastError()); 
      return 1; 
   } 
   else 
      printf("WSASocket() looks OK!\n"); 
  
   if ((EventArray[0] = WSACreateEvent()) == WSA_INVALID_EVENT) 
   { 
      printf("WSACreateEvent() failed with error %d\n", WSAGetLastError()); 
      return 1; 
   } 
   else 
      printf("WSACreateEvent() is OK!\n"); 
  
   // Áßø ÀÔÃâ·ÂÀ» ´Ù·ç±â À§ÇÑ ¾²·¹µå »ý¼º  
   if ( CreateThread(NULL, 0, ProcessIO, NULL, 0, &ThreadId) == NULL ) 
   { 
      printf("CreateThread() failed with error %d\n", GetLastError()); 
      return 1; 
   } 
   else 
      printf("Nothing to say, CreateThread() is OK!\n"); 
  
   EventTotal = 1; 
 
   // ¸ÞÀÎ ¾²·¹µå´Â accept 󸮸¸ ´ã´çÇÑ´Ù.  
   while(TRUE) 
   { 
      // Ŭ¶óÀÌ¾ðÆ® ¿¬°á ¿äûÀ» °¡Á®¿Â´Ù. 
      if ((AcceptSocket = accept(ListenSocket, NULL, NULL)) == INVALID_SOCKET) 
      { 
          printf("accept() failed with error %d\n", WSAGetLastError()); 
          return 1; 
      } 
      else 
          printf("accept() is OK!\n"); 
 
      // ¼º°øÀûÀ¸·Î ¿¬°á ¼ÒÄÏÀ» °¡Á®¿À¸é, À̺¥Æ® Á¤º¸ ¹è¿­°ú ¼ÒÄÏ Á¤º¸ ¹è¿­¿¡ Á¤º¸¸¦ Ãß°¡Çϰí 
      // Áßø ÀÔÃâ·Â ¿¬»êÀ» ¼öÇàÇÑ´Ù. 
      EnterCriticalSection(&CriticalSection); 
 
      if ((SocketArray[EventTotal] = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR, sizeof(SOCKET_INFORMATION))) == NULL) 
      { 
         printf("GlobalAlloc() failed with error %d\n", GetLastError()); 
         return 1; 
      } 
      else 
         printf("GlobalAlloc() for LPSOCKET_INFORMATION is pretty fine!\n"); 
  
      // ¿¬°á ¼ÒÄÏ Á¤º¸¸¦ ¼ÒÄÏ Á¤º¸ ±¸Á¶Ã¼ ¹è¿­¿¡ Ãß°¡ÇÑ´Ù.  
      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\n", WSAGetLastError()); 
         return 1; 
      } 
      else 
         printf("WSACreateEvent() is OK!\n"); 
  
      // 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\n", WSAGetLastError()); 
            return 1; 
         } 
      } 
      else 
            printf("WSARecv() should be working!\n"); 
  
      EventTotal++; 
      LeaveCriticalSection(&CriticalSection); 
  
      // ¿öÄ¿ ¾²·¹µå¿¡ À̺¥Æ®¸¦ Çѹø º¸³»º»´Ù. 
      if (WSASetEvent(EventArray[0]) == FALSE) 
      { 
         printf("WSASetEvent() failed with error %d\n", WSAGetLastError()); 
         return 1; 
      } 
      else 
         printf("Don't worry, WSASetEvent() is OK!\n"); 
   } 
} 
  
DWORD WINAPI ProcessIO(LPVOID lpParameter) 
{ 
   DWORD Index; 
   DWORD Flags; 
   LPSOCKET_INFORMATION SI; 
   DWORD BytesTransferred; 
   DWORD i; 
   DWORD RecvBytes, SendBytes; 
  
   while(TRUE) 
   { 
      // wait ÇÔ¼ö·Î À̺¥Æ®¸¦ ±â´Ù¸°´Ù. 
      if ((Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE,  WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED) 
      { 
         printf("WSAWaitForMultipleEvents() failed %d\n", WSAGetLastError()); 
         return 0; 
      } 
      else 
         printf("WSAWaitForMultipleEvents() is OK!\n"); 
  
      // 0 ¹ø À̺¥Æ® °´Ã¼¿¡¼­ÀÇ À̺¥Æ®´Â µè±â ¼ÒÄÏ¿¡ °ü·ÃµÈ °ÍÀÌ´Ù.  
      // ¹«½ÃÇÏ°í ³Ñ¾î°£´Ù. 
      if ((Index - WSA_WAIT_EVENT_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\n", SI->Socket); 
  
         if (closesocket(SI->Socket) == SOCKET_ERROR) 
         { 
            printf("closesocket() failed with error %d\n", WSAGetLastError()); 
         } 
         else 
            printf("closesocket() is OK!\n"); 
  
         GlobalFree(SI); 
         WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]); 
         // Cleanup SocketArray and EventArray by removing the socket event handle 
         // and socket information structure if they are not at the end of the arrays 
         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; 
      } 
 
 
      if (SI->BytesRECV == 0) 
      { 
         SI->BytesRECV = BytesTransferred; 
         SI->BytesSEND = 0; 
      } 
      else 
      { 
         SI->BytesSEND += BytesTransferred; 
      } 
  
      if (SI->BytesRECV > SI->BytesSEND) 
      { 
         // Post another WSASend() request. 
         // Since WSASend() is not guaranteed to send all of the bytes requested, 
         // continue posting WSASend() calls until all received bytes are sent 
         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\n", WSAGetLastError()); 
               return 0; 
            } 
         } 
         else 
              printf("WSASend() is OK!\n"); 
      } 
      else 
      { 
         SI->BytesRECV = 0; 
         // Now that there are no more bytes to send post another WSARecv() request 
         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\n", WSAGetLastError()); 
               return 0; 
            } 
         } 
         else 
             printf("WSARecv() is OK!\n"); 
      } 
   } 
} 
 

1.1.2 Äݹé ÇÔ¼ö È£Ãâ

Äݹé ÇÔ¼ö È£Ãâ ±â¹ÝÀÇ °£´ÜÇÑ ¿¡ÄÚ ¼­¹ö ÇÁ·Î±×·¥

#include <winsock2.h> 
#include <windows.h> 
#include <stdio.h> 
 
#define MAXLINE 1024 
 
// Áßø Á¤º¸¸¦ ºñ·ÔÇÑ ¼ÒÄÏ Á¤º¸¸¦ ÀúÀåÇϱâ À§ÇÑ ±¸Á¶Ã¼ 
struct SOCKETINFO 
{ 
    WSAOVERLAPPED overlapped; 
    SOCKET fd; 
    WSABUF dataBuf; 
    char buf[MAXLINE]; 
    int readn; 
    int writen; 
}; 
 
// ÀÔÃâ·Â ¿Ï·á½Ã È£ÃâÇÒ Äݹé ÇÔ¼ö 
void CALLBACK WorkerRoutine(DWORD Error, DWORD readn, LPWSAOVERLAPPED overlapped, DWORD lnFlags); 
 
int main(int argc, char **argv) 
{ 
    WSADATA wsaData; 
    SOCKET listen_fd, client_fd; 
    struct sockaddr_in addr; 
    struct SOCKETINFO *sInfo; 
    int flags; 
    int readn; 
 
    if(argc != 2) 
    { 
        printf("Usage : %s [port number]\n", argv[0]); 
        return 1; 
    } 
    if(WSAStartup( MAKEWORD(2,2), &wsaData) != 0 ) 
    { 
        return 1; 
    } 
    if( (listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET ) 
    { 
        return 1; 
    } 
 
    addr.sin_family = AF_INET; 
    addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    addr.sin_port = htons(atoi(argv[1])); 
 
    if( bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR ) 
    { 
        return 1; 
    } 
    if( listen(listen_fd, 5) == SOCKET_ERROR ) 
    { 
        return 1; 
    } 
 
    while(1) 
    { 
                // accept ÇÔ¼ö´Â Áßø ÀÔÃâ·ÂÀ» »ç¿ëÇÏÁö ¾Ê¾Ò´Ù. 
                // Áßø ÀÔÃâ·Â ¸ðµ¨À» »ç¿ëÇØ¼­ º°µµÀÇ ¿Ï·á ·çƾÀ» È£ÃâÇϱ⠿øÇÑ´Ù¸é, accetEx ÇÔ¼ö¸¦ È£ÃâÇØ¾ß ÇÑ´Ù. 
        if( (client_fd = accept(listen_fd, NULL, NULL)) == INVALID_SOCKET) 
        { 
            printf("Accept Error\n"); 
            return 1; 
        } 
 
        sInfo = (void *)malloc(sizeof(struct SOCKETINFO)); 
        memset((void *)sInfo, 0x00, sizeof(struct SOCKETINFO)); 
 
        sInfo->fd = client_fd; 
        sInfo->dataBuf.len = MAXLINE; 
        sInfo->dataBuf.buf = sInfo->buf; 
 
        flags = 0; 
 
                // ÀÔ·ÂÀÌ ¿Ï·áµÇ¸é WorkerRoutine¸¦ È£ÃâÇÑ´Ù. 
        if( WSARecv(sInfo->fd, &sInfo->dataBuf, 1, &readn, &flags, &(sInfo->overlapped), WorkerRoutine) == SOCKET_ERROR ) 
        { 
            if( WSAGetLastError() != WSA_IO_PENDING ) 
            { 
                printf("wsarecv error %d\n", WSAGetLastError()); 
            } 
        } 
    } 
    return 1; 
} 
 
void CALLBACK WorkerRoutine(DWORD Error, DWORD transfern, LPWSAOVERLAPPED overlapped, DWORD lnFlags) 
{ 
    struct SOCKETINFO *si; 
 
    int readn, writen; 
    int flags = 0; 
    si = (struct SOCKETINFO *)overlapped; 
 
    if(transfern == 0) 
    { 
        printf("socket close\n"); 
        closesocket(si->fd); 
        free(si); 
        return ; 
    } 
     
        // readnÀÌ 0À̶ó´Â ¾ê±â´Â ÇöÀç ÀÌ Äݹé ÇÔ¼ö´Â ÀԷ¿Ϸᰡ µÇ¾î¼­ È£Ã⠵ǾúÀ½À» ÀǹÌÇÑ´Ù. 
    if(si->readn == 0) 
    { 
        si->readn = transfern; 
        si->writen = 0; 
    } 
    else 
    { 
        si->writen += transfern; 
    } 
 
        // ¸¸¾à ¾´ µ¥ÀÌÅͰ¡ ÀÐÀº µ¥ÀÌÅÍ º¸´Ù ÀÛ´Ù¸é, ÀÐÀº µ¥ÀÌÅ͸¦ ¸ðµÎ Àü¼ÛÇÏÁö ¾Ê¾ÒÀ½À» ÀǹÌÇÏ´Ù. 
        // ÀÐÀº µ¥ÀÌÅ͸¦ ¸ðµÎ Àü¼ÛÇÒ ¶§ ±îÁö WSASend¸¦ °è¼Ó È£Ãâ ÇÑ´Ù. 
    if(si->readn > si->writen) 
    { 
        memset(&(si->overlapped), 0x00, sizeof(WSAOVERLAPPED)); 
        si->dataBuf.buf = si->buf + si->writen; 
        si->dataBuf.len = si->readn - si->writen; 
         
        if( WSASend(si->fd, &(si->dataBuf), 1, &writen, 0, &(si->overlapped), WorkerRoutine) == SOCKET_ERROR ) 
        { 
            if(WSAGetLastError() != WSA_IO_PENDING) 
            { 
                printf("WSASend Error\n"); 
            } 
        } 
    } 
    else 
    { 
        si->readn = 0; 
        flags = 0; 
        memset(&(si->overlapped), 0x00, sizeof(WSAOVERLAPPED)); 
        si->dataBuf.len = MAXLINE; 
        si->dataBuf.buf = si->buf; 
        if( WSARecv(si->fd, &si->dataBuf, 1, &readn, &flags, &(si->overlapped), WorkerRoutine) == SOCKET_ERROR) 
        { 
            if( WSAGetLastError() != WSA_IO_PENDING ) 
            { 
                printf("wsarecv error %d\n", WSAGetLastError()); 
            } 
        } 
    } 
    return ; 
} 
 

category_network
programing
category__5
EmailÀ» ±âÀÔÇϸé, ´ñ±ÛÀÌ ¸ÞÀÏ·Î Àü´ÞµË´Ï´Ù.