Programming °æ (¾«»ªÇø)

·¢ÐÅÈË: superman (·çÓêÎÞ×è), ÐÅÇø: Programming
±ê  Ìâ: ¼òµ¥µÄ Winsock Ó¦ÓóÌʽÉè¼Æ£¨1)(fwd) (תÔØ)
·¢ÐÅÕ¾: ×϶¡Ïã (Thu Oct  9 21:55:36 1997)

¡¾ ÒÔÏÂÎÄ×ÖתÔØ×Ô Winsock ÌÖÂÛÇø ¡¿
¡¾ Ô­ÎÄÓÉ topcon Ëù·¢±í ¡¿
·¢ÐÅÕ¾: °×ɽºÚË® (Tue Apr 23 21:25:27 1996)


¼òµ¥µÄ Winsock Ó¦ÓóÌʽÉè¼Æ£¨1£©

        ÁÖ ¾ü Ø¾

ÏàП÷λ¶ÁÕßÏÖÔÚ¶Ô춠Winsock µÄ¶¨Ò塢ϵͳ»·¾³£¬ÒÔ¼°Ò»Ð© Winsock Stack
¼° Winsock Ó¦ÓóÌʽ£¬¶¼Óлù±¾µÄÈÏʶÁË¡£½ÓÏÂÀ´±ÊÕßÏ£ÍûÄÜ·Ö¼¸ÆÚΪ¸÷λ¶ÁÕß
½éÉÜһϼòµ¥µÄ Winsock Íø·ӦÓóÌʽÉè¼Æ¡£

ÎÒÃǽ«ÒÔ Winsock 1.1 ¹æ¸ñËù¶¨ÒåµÄ 46 ¸öÓ¦ÓóÌʽ½éÃ棨API£©Îª»ù´¡£¬Öð
²½À´½¨Á¢Ò»¶Ô TCP socket Ö÷´Ó¼Ü¹¹£¨Client / Server£©µÄ³Ìʽ¡£ÔÚÕâÁ½¸ö³ÌʽÖУ¬
Server ½«Ê¹ÓàWinsock ÌṩµÄ¡¸·Çͬ²½¡¹£¨asynchronous£©º¯Ê½À´½¨Á¢ socket Á¬
½á¡¢¹Ø±Õ¡¢¼°×ÊÁÏÊÕË͵ȵȣ»¶ø Client Ôò²ÉÀàËÆ´«Í³ UNIX µÄ¡¸×èÀ¹Ê½¡¹
£¨blocking£©¡£ÓÉì¶ÎÒÃǵÄÖص㲢²»ÔÚ춠MS Windows SDK µÄ³ÌʽÉè¼Æ£¬ËùÒÔÎÒ
Ãǽ«Ê¹ÓÃ×î¼ò±ãµÄ·½Ê½À´ÏÔʾѶϢ£»ÓйؠMS Windows ³ÌʽµÄ¼¼ÇÉ£¬Çë¸÷λ¶ÁÕß
×ÔÐÐÑо¿Ïà¹ØµÄÊé¼®¼°ÎÄÕ¡£

½ñÌìÎÒÃÇÏÈÒª¿´Ò»ÏÂÖ÷´Ó¼Ü¹¹ TCP socket µÄ½¨Á¢Á¬½á£¨connect£©¼°¹Ø±Õ
£¨close£©¡££¨²Î¼ûͼ 1.£©


£¨Í¼ 1. Ö÷´Ó¼Ü¹¹µÄ TCP socket Á¬½Ó½¨Á¢Óë¹Ø±Õ£©

ÒÔÇ°±ÊÕßÔø¼òµ¥µØ½éÉܹýÖ÷´Ó¼Ü¹¹µÄ¸ÅÄÏÖÔÚÎÒÃÇÔÙÒÔÉú»îÉϸüdzÏÔµÄÀý
×ÓÀ´ËµÃ÷һϣ¬¶ÁÕßÉÔááÒ²½ÏÈÝÒ×ÄÜÃ÷°×±ÊÕßµÄÐðÊö¡£ÎÒÃÇ¿ÉÒÔ¼ÙÉè Server ¾ÍÏñ
ÊǵçОÖËùÌṩµÄһЩ·þÎñ£¬±ÈÈ硸104 ²éºĄ̊¡¹»ò¡¸112 ÕÏ°­Ì¨¡¹¡£

£¨1£©µçОÖÏȽ¨Á¢ºÃÁËÒ»¸öµç»°×Ü»ú£¬Õâ¾ÍÏñÊǺô½Ð socket() º¯Ê½¿ªÆôÁËÒ»
¸ö socket¡£
£¨2£©½ÓÖøµçОֽ«Õâ¸ö×Ü»úµÄºÅÂ붨Ϊ 104£¬¾ÍÈçͬÎÒÃǺô½Ð bind() º¯Ê½£¬
½« Server µÄÕâ¸ö socket Ö¸¶¨£¨bind£©ÔÚijһ¸ö port¡£µ±È»µçОֱØÐëÈÃÓû§ÖªµÀ
Õâ¸öºÅÂ룻¶øÎÒÃǵĠClient ³ÌʽͬÑùÒ²ÒªÖªµÀ Server ËùÓõĠport£¬´ý»á²ÅÓа취
ÓëÖ®Á¬½Ó¡£
£¨3£©µçОֵĠ104 ²éºĄ̊µ×Ï»áÓÐһЩ×Ô¶¯·þÎñµÄ·Ö»ú£¬µ«ÊÇËüµÄÊýÁ¿ÊÇÓÐ
Ï޵ģ¬ËùÒÔÓÐʱÄã»á²¦²»Í¨Õâ¸öºÅÂ루æÏߣ©¡£Í¬ÑùµØ£¬ÎÒÃÇÔÚ½¨Á¢Ò»¸ö TCP µÄ
Server socket Ê±£¬Ò²»áºô½Ð listen() º¯Ê½À´¼àÌýµÈ´ý£»listen() µÄµÚ¶þ¸ö²ÎÊý¼´ÊÇ
waiting queue µÄÊýÄ¿£¬Í¨³£ÊýÖµÊÇÓÉ 1 µ½ 5¡££¨ÊÂʵÉÏÕâÁ½Õß»¹ÊÇÓе㲻һ
Ñù¡££©
£¨4£©Óû§ÖªµÀÁ˵çОֵÄÕâ¸ö 104 ²éºÅ·þÎñ£¬Ëû¾Í¿ÉÒÔÀûÓÃij¸öµç»°À´²¦ºÅ
Á¬½ÓÕâ¸ö·þÎñÁË¡£Õâ¾ÍÊÇÎÒÃÇ Client ³Ìʽ¿ªÆôÒ»¸öÏàͬµÄ TCP socket£¬È»ááºô½Ð
connect() º¯Ê½È¥Á¬½Ó Server Ö¸¶¨µÄÄǸö port¡£µ±È»ÁË£¬ºÍµç»°Ò»Ñù£¬Èç¹û waiting
queue ÂúÁË¡¢Óë Server ¼äÏß·²»Í¨¡¢»òÊÇ Server Ã»Ìṩ´ËÏî·þÎñʱ£¬ÄãµÄÁ¬½Ó¾Í
»áʧ°Ü¡£
£¨5£©µçОֲéºĄ̊µÄ×Ü»ú½ÓÊÜÁËÕâͨ²éѯµÄµç»°áᣬËü»áתµ½ÁíÒ»¸ö·Ö»ú×ö
·þÎñ£¬¶ø×Ü»ú±¾ÉíÔòÔٻص½µÈ´ýµÄ״̬¡£Server µÄ listening socket ÒàÊÇÒ»Ñù£¬µ±
Äãºô½ÐÁË accept() º¯Ê½Ö®áᣬServer ¶ËµÄϵͳ»á½¨Á¢Ò»¸öеĠsocket À´¶Ô´ËÁ¬½Ó
×ö·þÎñ£¬¶øÔ­ÏȵĠsocket ÔòÔٻص½¼àÌýµÈ´ýµÄ״̬¡£
£¨6£©µ±Äã²éѯÍê±ÏÁË£¬Äã¾Í¿ÉÒÔ¹ÒÉϵ绰£¬±Ë´Ë¼äÒ²¾ÍÀëÏßÁË¡£Client ºÍ
Server ¼äµÄ socket ¹Ø±ÕÒàÊÇÈç´Ë£»²»¹ýÕâ¸ö¹Ø±ÕÀëÏߵĶ¯×÷£¬¿ÉÓÉ Client ¶Ë»ò
Server ¶ËÈÎÒ»·½Ïȹرա£ÓÐЩµç»°²éѯϵͳ²»Ò²ÊÇÈç´ËÂð£¿

½ÓÏÂÀ´£¬ÎÒÃǾÍÀ´¿´Ö÷´Ó¼Ü¹¹µÄ TCP socket ÊÇÈçºÎÀûÓÃÕâЩ Winsock º¯Ê½À´
´ï³ÉµÄ£»²¢ÀûÓÃ×ʲ߻á×ÊѶ¼¼Êõ´¦µÄ¡¸WinKing¡¹Õâ¸ö Winsock Stack ÖÐijÏÄÜ
À´ÏÔʾ sockets ×´Ì¬µÄ±ä»¯¡£ÎÄÕÂÖнöÁгö³ÌʽµÄƬ¶Î£¬ÍêÕûµÄ³ÌʽÇë¿´¸½Â¼µÄ³Ì
ʽ¡£

¡¾Server ¶Ë½¨Á¢ socket ²¢½øÈë¼àÌýµÈ´ý״̬¡¿

Ê×ÏÈÎÒÃÇÏÈ¿´ Server ¶ËÈçºÎ½¨Á¢Ò»¸ö TCP socket£¬²¢Ê¹Æä½øÈë¼àÌýµÈ´ýµÄ×´
̬¡£

ÔÚͼ 1. ÉÏ£¬ÎÒÃÇ¿ÉÒÔ¿´µ½×îÏȱ»ºô½Ðµ½µÄÊÇ WSAStartup() º¯Ê½¡£ËµÃ÷ÈçÏ£º

WSAStartup()£ºÁ¬½áÓ¦ÓóÌʽÓë Winsock.DLL µÄµÚÒ»¸öº¯Ê½¡£
¸ñ  Ê½£º int PASCAL FAR WSAStartup( WORD wVersionRequested,
LPWSADATA lpWSAData );
²Î  Êý£º        wVersionRequested       ÓûʹÓõĠWindows Sockets API °æ±¾
        lpWSAData               Ö¸Ïò WSADATA ×ÊÁϵÄÖ¸±ê
´«»ØÖµ£º        ³É¹¦ - 0
        Ê§°Ü - WSASYSNOTREADY / WSAVERNOTSUPPORTED /
WSAEINVAL
˵Ã÷£º ´Ëº¯Ê½¡¸±ØÐ롹ÊÇÓ¦ÓóÌʽºô½Ðµ½ Windows Sockets DLL º¯Ê½ÖеĵÚÒ»
¸ö£¬Ò²Î¨Óд˺¯Ê½ºô½Ð³É¹¦áᣬ²Å¿ÉÒÔÔÙºô½ÐÆäËû Windows  Sockets DLL µÄº¯Ê½¡£
´Ëº¯Ê½ÒàÈÃʹÓÃÕß¿ÉÒÔÖ¸¶¨ÒªÊ¹ÓõĠWindows Sockets API °æ±¾£¬¼°»ñÈ¡Éè¼ÆÕßµÄ
һЩ×ÊѶ¡£

³ÌʽÖÐÎÒÃÇÒªÓàWinsock 1.1£¬ËùÒÔÎÒÃÇÔÚ³ÌʽÖÐÓÐÒ»¶ÎΪ£º

WSAStartup((WORD)((1<<8)|1),(LPWSADATA) &WSAData)

ÆäÖР((WORD)((1<<8)|1) ±íʾÎÒÃÇÒªÓõÄÊÇ Winsock ¡¸1.1¡¹°æ±¾£¬¶ø
WSAData ÔòÊÇÓÃÀ´´¢´æÓÉϵͳ´«»ØµÄһЩÓйشËÒ» Winsock Stack µÄ×ÊÁÏ¡£

ÔÙÀ´ÎÒÃǺô½Ð socket() º¯Ê½À´¿ªÆô Server ¶ËµÄ TCP socket¡£

socket()£º½¨Á¢Socket¡£
¸ñ  Ê½£º SOCKET PASCAL FAR socket( int af, int type,  int protocol );
²Î  Êý£º af     Ä¿Ç°Ö»Ìṩ PF_INET(AF_INET)
        type    Socket µÄÐÍ̬ (SOCK_STREAM¡¢SOCK_DGRAM)
        protocol        Í¨Ñ¶Ð­¶¨(Èç¹ûʹÓÃÕß²»Ö¸¶¨ÔòÉèΪ0)
´«»ØÖµ£º ³É¹¦ - Socket µÄʶ±ðÂë
          Ê§°Ü - INVALID_SOCKET(ºô½Ð WSAGetLastError() ¿ÉµÃÖªÔ­Òò)
˵Ã÷£º ´Ëº¯Ê½ÓÃÀ´½¨Á¢Ò» Socket£¬²¢Îª´Ë Socket ½¨Á¢ÆäËùʹÓõÄ×ÊÔ´¡£
 Socket µÄÐÍ̬¿ÉΪ Stream Socket »ò Datagram Socket¡

ÎÒÃÇÒª½¨Á¢µÄÊÇ TCP socket£¬ËùÒÔ³ÌʽÖÐÎÒÃǵĵڶþ¸ö²ÎÊýΪ
SOCK_STREAM£¬ÎÒÃDz¢½«¿ªÆôµÄÕâ¸ö socket ºÅÂë¼ÇÔÚ listen_sd Õâ¸ö±äÊý¡£

listen_sd = socket(PF_INET, SOCK_STREAM, 0)

½ÓÏÂÀ´ÎÒÃÇÒªÖ¸¶¨Ò»¸öλַ¼° port ¸ø Server µÄÕâ¸ö socket£¬ÕâÑù Client ²ÅÖª
µÀ´ý»áÒªÁ¬½ÓÄÄÒ»¸öλַµÄÄĸö port£»ËùÒÔÎÒÃǺô½Ð bind() º¯Ê½¡£

bind()£ºÖ¸¶¨ Socket µÄ Local Î»Ö· (Address)¡£
¸ñ  Ê½£º int PASCAL FAR bind( SOCKET s, const struct sockaddr FAR *name,
                                                int namelen );
²Î  Êý£º s      SocketµÄʶ±ðÂë
        name    SocketµÄλֵַ
        namelen nameµÄ³¤¶È
´«»ØÖµ£º ³É¹¦ - 0
        Ê§°Ü - SOCKET_ERROR  (ºô½Ð WSAGetLastError() ¿ÉµÃÖªÔ­Òò)
˵Ã÷£º ´ËÒ»º¯Ê½ÊÇÖ¸¶¨ Local Î»Ö·¼° Port ¸øijһ䶨ÃûÖ® Socket¡£Ê¹ÓÃÕßÈô²»
ÔÚÒâλַ»ò Port µÄÖµ£¬ÄÇ÷áËû¿ÉÒÔÉ趨λַΪ INADDR_ANY£¬¼°  Port Îª 0£»ÄÇ÷á
Windows Sockets »á×Ô¶¯½«ÆäÉ趨Êʵ±Ö®Î»Ö·¼° Port  (1024 µ½ 5000Ö®¼äµÄÖµ)£¬Ê¹ÓÃ
Õß¿ÉÒÔÔÚ´Ë Socket ÕæÕýÁ¬½ÓÍê³Éáᣬºô½Ð getsockname() À´»ñÖªÆä±»É趨µÄÖµ¡£

bind() º¯Ê½ÒªÖ¸¶¨Î»Ö·¼° port£¬Õâ¸öλַ±ØÐëÊÇÖ´ÐÐÕâ¸ö³ÌʽËùÔÚ»úÆ÷µÄ IP
λַ£¬ËùÒÔÈç¹û¶ÁÕßÔÚÉè¼Æ³Ìʽʱ¿ÉÒÔ½«Î»Ö·É趨Ϊ INADDR_ANY£¬ÕâÑù
Winsock ÏµÍ³»á×Ô¶¯½«»úÆ÷ÕýÈ·µÄλַÌîÈë¡£Èç¹ûÄúÒªÈóÌʽֻÄÜÔÚij̨»úÆ÷ÉÏ
Ö´ÐеĻ°£¬ÄÇ÷á¾Í½«Î»Ö·É趨Ϊ¸Ą̃»úÆ÷µÄ IP Î»Ö·¡£ÓÉ춴˶ËÊÇ Server ¶Ë£¬Ëù
ÒÔÎÒÃÇÒ»¶¨ÒªÖ¸¶¨Ò»¸ö port ºÅÂë¸øÕâ¸ö socket¡£

¶ÁÕß±ØÐë×¢ÒâÒ»µã£¬TCP socket Ò»µ©Ñ¡¶¨ÁËÒ»¸öλַ¼° port áᣬ¾ÍÎÞ·¨ÔÙºô
½ÐÁíÒ»´Î bind À´ÈÎÒâ¸ü¸ÄËüµÄλַ»ò port¡£

ÔÚ³ÌʽÖÐÎÒÃǽ« Server ¶ËµÄ port Ö¸¶¨Îª 7016£¬Î»Ö·ÔòÓÉϵͳÀ´É趨¡£

struct sockaddr_in sa;
sa.sin_family = PF_INET;
sa.sin_port = htons(7016);          /* port number */
sa.sin_addr.s_addr = INADDR_ANY;    /* address */
bind(listen_sd, (struct sockaddr far *)&sa, sizeof(sa))

ÎÒÃÇÔÚÖ¸¶¨ port ºÅÂëʱ»áÓõ½ htons() Õâ¸öº¯Ê½£¬Ö÷ÒªÊÇÒòΪ¸÷»úÆ÷µÄÊýÖµ¶Á
È¡·½Ê½²»Í¬£¨PC Óë UNIX ÏµÍ³¼´²»Ïàͬ£©£¬ËùÒÔÎÒÃÇÀûÓÃÕâ¸öº¯Ê½À´½« host
order µÄÅÅÁз½Ê½×ª»»³É network order µÄÅÅÁз½Ê½£»ÏàͬµØ£¬ÎÒÃÇÒ²¿ÉÒÔºô½Ð
ntohs() Õâ¸öÏà¶ÔµÄº¯Ê½½«Æ仹ԭ¡££¨host order ¸÷»úÆ÷²»Í¬£¬µ« network order ¶¼
Ïàͬ£©£¨htons ÊÇÕë¶Ô short ÊýÖµ£¬¶Ô춠long ÊýÖµÔòÓàhotnl ¼° ntohl£©

Ö¸¶¨Íêλַ¼° port Ö®áᣬÎÒÃǺô½Ð listen() º¯Ê½£¬ÈÃÕâ¸ö socket ½øÈë¼àÌý×´
̬¡£Ò»¸ö Server ¶ËµÄ TCP socket ±ØÐëÔÚ×öÍêÁË listen µÄºô½Ðáᣬ²ÅÄܽÓÊÜ Client
¶ËµÄÁ¬½Ó¡£

listen()£ºÉ趨 Socket Îª¼àÌý״̬£¬×¼±¸±»Á¬½Ó¡£
¸ñ  Ê½£º int PASCAL FAR listen( SOCKET s, int backlog );
²Î  Êý£º s      Socket µÄʶ±ðÂë
        backlog Î´ÕæÕýÍê³ÉÁ¬½ÓÇ°(ÉÐδºô½Ð accept Ç°)±Ë¶ËµÄÁ¬½ÓÒªÇóµÄ×î´ó
¸öÊý
´«»ØÖµ£º ³É¹¦ - 0
                  Ê§°Ü - SOCKET_ERROR (ºô½Ð WSAGetLastError() ¿ÉµÃÖªÔ­Òò)
˵Ã÷£º Ê¹ÓÃÕß¿ÉÀûÓô˺¯Ê½À´É趨 Socket ½øÈë¼àÌý״̬£¬²¢É趨×î¶à¿ÉÓжàÉÙ
¸öÔÚδÕæÕýÍê³ÉÁ¬½ÓÇ°µÄ±Ë¶ËµÄÁ¬½ÓÒªÇó¡£(Ä¿Ç°×î´óÖµÏÞÖÆΪ 5, ×îСֵΪ1)

³ÌʽÖÐÎÒÃǽ« backlog ÉèΪ 1 ¡£

listen(listen_sd, 1)

ºô½ÐÍê listen áᣬ´Ëʱ Client ¶ËÈç¹ûÀ´Á¬½ÓµÄ»°£¬Client ¶ËµÄÁ¬½Ó¶¯×÷
£¨connect£©»á³É¹¦£¬²»¹ý´Ëʱ Server ¶Ë±ØÐëÔÙºô½Ð accept() º¯Ê½£¬²ÅËãÕýʽÍê³É
Server ¶ËµÄÁ¬½Ó¶¯×÷¡£µ«ÊÇÎÒÃÇʲ÷áʱºò¿ÉÒÔÖªµÀ Client ¶ËÀ´Á¬½Ó£¬¶øÊÊʱµØºô
½Ð accept ÄØ£¿ÔÚÕâÀïÎÒÃǾÍÒªÀûÓÃÒ»¸öºÜºÃÓõĠWSAAsyncSelect º¯Ê½£¬½«
Server ¶ËµÄÕâ¸ö socket ×ª±ä³É Asynchronous Ä£Ê½£¬ÈÃϵͳÖ÷¶¯À´Í¨ÖªÎÒÃÇÓÐ
Client ÒªÁ¬½ÓÁË¡££¨Í¼1. Öв¢Î´½«´Ëº¯Ê½»æ³ö£©

WSAAsyncSelect()£ºÒªÇóijһ Socket ÓÐʼþ (event) ·¢Éúʱ֪ͨʹÓÃÕß¡£
¸ñ  Ê½£º int PASCAL FAR WSAAsyncSelect( SOCKET s, HWND hWnd,
                                unsigned int wMsg, long lEvent );
²Î  Êý£º s      Socket µÄ±àºÅ
                hWnd    ¶¯×÷Íê³Éáᣬ½ÓÊÜѶϢµÄÊÓ´° handle
                wMsg    ´«»ØÊÓ´°µÄѶϢ
        lEvent  Ó¦ÓóÌʽÓÐÐËȤµÄÍø·Ê¼þ
´«»ØÖµ£º ³É¹¦ - 0
          Ê§°Ü - SOCKET_ERROR (ºô½Ð WSAGetLastError() ¿ÉµÃÖªÔ­Òò)
˵Ã÷£º ´Ëº¯Ê½ÊÇÈÃʹÓÃÕßÓÃÀ´ÒªÇó Windows Sockets DLL ÔÚÕì²âµ½Ä³Ò»  Socket
ÓÐÍø·Ê¼þʱËÍѶϢµ½Ê¹ÓÃÕßÖ¸¶¨µÄÊÓ´°£»Íø·Ê¼þÊÇÓɲÎÊý lEvent É趨¡£ºô½Ð´Ë
º¯Ê½»áÖ÷¶¯½«¸Ã Socket É趨Ϊ Non-blocking Ä£Ê½¡£lEvent µÄÖµ¿ÉΪÒÔÏÂÖ®¡¸OR¡¹
×éºÏ£º(²Î¼û WINSOCKµÚ1.1°æ88¡¢89Ò³) FD_READ¡¢FD_WRITE¡¢FD_OOB¡¢
FD_ACCEPT¡¢FD_CONNECT¡¢FD_CLOSE  Ê¹ÓÃÕßÈôÊÇÕë¶ÔijһSocketÔٴκô½Ð
´Ëº¯Ê½Ê±£¬»áÈ¡Ïû¶Ô¸Ã Socket   Ô­ÏÈÖ®É趨¡£ÈôҪȡÏû¶Ô¸ÃSocket µÄËùÓÐÉ趨£¬Ôò
lEvent µÄÖµ±ØÐëÉèΪ 0¡£


        £¨Í¼2£© WSAAsyncSelect º¯Ê½²ÎÊýÓëÓ¦ÓóÌʽ¹Øϵ

ÎÒÃÇÔÚ³ÌʽÖÐÒªÇó Winsock ÏµÍ³ÖªµÀ Client ÒªÀ´Á¬½Óʱ£¬ËÍÒ»¸ö
ASYNC_EVENT µÄѶϢµ½³ÌʽÖРhwnd Õâ¸öÊÓ´°£»ÓÉì¶ÎÒÃÇÏëÖªµÀµÄÖ»ÓРaccept ÊÂ
¼þ£¬ËùÒÔÎÒÃÇÖ»É趨 FD_ACCEPT¡£

WSAAsyncSelect(listen_sd, hwnd, ASYNC_EVENT, FD_ACCEPT)


£¨Í¼ 3£©demoserv ÔÚ WinKing ÏµÍ³ÉϽ¨Á¢ socket ²¢½øÈë¼àÌý״̬

¶ÁÕß±ØÐë×¢ÒâÒ»µã£¬WSAAsyncSelect µÄÉ趨ÊÇÕë¶Ô¡¸Ä³Ò»¸ö socket¡¹£»Ò²¾ÍÊÇ
˵£¬Ö»Óе±ÄúÉ趨µÄÕâ¸ö socket £¨listen_sd£©µÄÄÇЩʼþ£¨FD_ACCEPT£©·¢Éúʱ£¬
Äú²Å»áÊÕµ½Õâ¸öѶϢ£¨ASYNC_EVENT£©¡£Èç¹ûÄú¿ªÆôÁ˺ܶà sockets£¬¶øÒªÈÃÿ
¸ö socket ¶¼±ä³É asynchronous Ä£Ê½µÄ»°£¬ÄÇ÷á¾Í±ØÐë¶Ô¡¸Ã¿Ò»¸ö socket¡¹¶¼ºô½Ð
WSAAsyncSelect À´Ò»Ò»É趨¡£¶øÈç¹ûÄúÏ뽫ijһ¸ö socket µÄ async Ê¼þ֪ͨÉ趨ȡ
ÏûµÄ»°£¬ÄÇ÷áͬÑùÒ²ÊÇÓàWSAAsyncSelect Õâ¸öº¯Ê½£»ÇÒµÚËĸö²ÎÊý lEvent Ò»¶¨Òª
ÉèΪ 0¡£

WSAAsyncSelect( s, hWnd, 0, 0 ) -- È¡ÏûËùÓРasync Ê¼þÉ趨

ÔÚÕâÀï±ÊÕß»¹Òª¸æË߸÷λһµã£¬ºô½Ð WSAAsyncSelect µÄͬʱҲ½«´ËÒ» socket
¸Ä±ä³É¡¸·Ç×èÀ¹¡¹£¨non-blocking£©Ä£Ê½¡£µ«ÊÇ´ËʱÕâ¸ö socket ²»Äܼܺòµ¥µØÓÃ
ioctlsocket() Õâ¸öº¯Ê½¾Í½«ËüÔÙ±ä»Ø¡¸×èÀ¹¡¹£¨blocking£©Ä£Ê½¡£Ò²¾ÍÊÇ˵
WSAAsyncSelect ºÍ ioctlsocket Ëù¸Ä±äµÄ¡¸·Ç×èÀ¹¡¹Ä£Ê½ÈÔÊÇÓÐЩ²»Í¬µÄ¡£Èç¹ûÄúÏë
½«Ò»¸ö¡¸·Çͬ²½¡¹£¨asynchronous£©Ä£Ê½µÄ socket ÔÙ±ä»Ø¡¸×èÀ¹¡¹Ä£Ê½µÄ»°£¬±ØÐë
ÏȺô½Ð WSAAsyncSelect() ½«ËùÓеĠasync Ê¼þÈ¡Ïû£¬ÔÙÓàioctlsocket() ½«Ëü±ä»Ø×è
À¹Ä£Ê½¡£

ioctlsocket()£º¿ØÖÆ Socket µÄģʽ¡£
¸ñ  Ê½£º int PASCAL FAR ioctlsocket( SOCKET s, long cmd, u_long  FAR *argP );
²Î  Êý£º        s       Socket µÄʶ±ðÂë
        cmd     Ö¸ÁîÃû³Æ
        argP    Ö¸Ïò cmd ²ÎÊýµÄÖ¸±ê
´«»ØÖµ£º ³É¹¦ - 0
                        Ê§°Ü - SOCKET_ERROR (ºô½Ð WSAGetLastError() ¿ÉµÃÖªÔ­Òò)
˵Ã÷£º ´Ëº¯Ê½ÓÃÀ´»ñÈ¡»òÉ趨 Socket µÄÔË×÷²ÎÊý¡£ÆäËùÌṩµÄÖ¸ÁîÓУº(²Î¼û
WINSOCK µÚ 1.1 °æ 35¡¢36 Ò³)
cmd µÄÖµ¿ÉΪ£º
FIONBIO    -- ¿ª¹Ø non-blocking Ä£Ê½
FIONREAD   -- ×Ô Socket Ò»´Î¿É¶ÁÈ¡µÄ×ÊÁÏÁ¿£¨Ä¿Ç° in buffer µÄ×ÊÁÏÁ¿£©
SIOCATMARK -- OOB ×ÊÁÏÊÇ·ñÒѱ»¶ÁÈ¡Íê

ÓÉì¶ÎÒÃÇ Server ¶ËµÄ socket ÊÇÓ÷Çͬ²½Ä£Ê½£¬ÇÒÉ趨ÁË FD_ACCEPT Ê¼þ£¬Ëù
ÒÔµ± Client ¶ËºÍÎÒÃÇÁ¬½Óʱ£¬Winsock Stack »áÖ÷¶¯Í¨ÖªÎÒÃÇ£»ÎÒÃÇÔÙÏÈÀ´¿´¿´
Client ¶ËÒªÈçºÎºÍ Server ¶Ë½¨Á¢Á¬½Ó£¿

¡¾Client ¶ËÏò Server ¶ËÖ÷¶¯½¨Á¢Á¬½Ó¡¿

Client Ê×ÏÈÒ²ÊǺô½Ð WSAStartup() º¯Ê½À´Óë Winsock Stack ½¨Á¢¹Øϵ£»È»ááͬÑù
ºô½Ð socket() À´½¨Á¢Ò»¸ö TCP socket¡££¨¶ÁÕß´Ëʱһ¶¨ÒªÓàTCP socket À´Á¬½Ó
Server ¶ËµÄ TCP socket£¬¶ø²»ÄÜÓàUDP socket À´Á¬½Ó£»ÒòΪÏàͬЭ¶¨µÄ sockets ²Å
ÄÜÏàͨ£¬TCP ¶Ô TCP£¬UDP ¶Ô UDP£©

ºÍ Server ¶ËµÄ socket ²»Í¬µÄµØ·½ÊÇ£ºClient ¶ËµÄ socket ¿ÉÒÔºô½Ð bind() º¯Ê½£¬
ÓÉ×Ô¼ºÀ´Ö¸¶¨ IP Î»Ö·¼° port ºÅÂ룻µ«ÊÇÒ²¿ÉÒÔ²»ºô½Ð bind()£¬¶øÓÉ Winsock Stack
À´×Ô¶¯É趨 IP Î»Ö·¼° port ºÅÂ루´ËÒ»¶¯×÷ÔÚºô½Ð connect() º¯Ê½Ê±»áÓÉ Winsock Ïµ
ͳÀ´Íê³É£©¡£Í¨³£ÎÒÃÇÊDz»ºô½Ð bind()£¬¶øÓÉϵͳÉ趨µÄ£¬ÉÔáá¿Éºô½Ð
getsockname() º¯Ê½À´¼ì²éϵͳ°ïÎÒÃÇÉ趨ÁËʲ÷á IP ¼° port¡£Ò»°ãÑÔ£¬ÏµÍ³»á×Ô¶¯
°ïÎÒÃÇÉ趨µÄ port ºÅÂëÊÇÔÚ 1024 µ½ 5000 Ö®¼ä£»¶øÈç¹û¶ÁÕßÒª×Ô¼ºÓàbind É趨 port
µÄ»°£¬×îºÃÊÇ 5000 ÒÔÉϵĺÅÂë¡£

connect()£ºÒªÇóÁ¬½Óijһ TCP Socket µ½Ö¸¶¨µÄ¶Ô·½¡£
¸ñ  Ê½£º int PASCAL FAR connect( SOCKET s, const struct sockaddr
                                FAR *name, int namelen );
²Î  Êý£º s       Socket µÄʶ±ðÂë
        name    ´Ë Socket ÏëÒªÁ¬½ÓµÄ¶Ô·½Î»Ö·
        namelen nameµÄ³¤¶È
´«»ØÖµ£º        ³É¹¦ - 0
        Ê§°Ü - SOCKET_ERROR (ºô½ÐWSAGetLastError()¿ÉµÃÖªÔ­Òò)
˵Ã÷£º ´Ëº¯Ê½ÓÃÀ´Ïò¶Ô·½ÒªÇó½¨Á¢Á¬½Ó¡£ÈôÊÇÖ¸¶¨µÄ¶Ô·½Î»Ö·Îª 0 µÄ»°£¬»á´«
»Ø´íÎóÖµ¡£µ±Á¬½Ó½¨Á¢Íê³ÉáᣬʹÓÃÕß¼´¿ÉÀûÓôËÒ» Socket À´×ö´«ËÍ»ò½ÓÊÕ×ÊÁÏÖ®
ÓÃÁË¡£

ÎÒÃǵÄÀý×ÓÖУ¬ Client ÊÇÒªÁ¬½ÓµÄÊÇ×Ô¼º»úÆ÷ÉÏ Server Ëù¼àÌýµÄ 7016 Õâ¸ö
port£¬ËùÒÔÎÒÃÇÓÐÒÔϵijÌʽƬ¶Î¡££¨¼ÙÉèÎÒÃÇ»úÆ÷µÄ IP ´æÔÚ my_host_ip£©

struct sockaddr_in sa;     /* ±äÊýÐû¸æ */
sa.sin_family       = PF_INET;     /* É趨ËùÒªÁ¬½ÓµÄ Server ¶Ë×ÊÁÏ */
sa.sin_port         = htons(7016);
sa.sin_addr.s_addr  = htonl(my_host_ip);
connect(mysd, (struct sockaddr far *)&sa, sizeof(sa))  /* ½¨Á¢Á¬½Ó */

¡¾Server ¶Ë½ÓÊÜ Client ¶ËµÄÁ¬½Ó¡¿

ÓÉì¶ÎÒÃÇ Server ¶ËµÄ socket ÊÇÉ趨Ϊ¡¸·Çͬ²½Ä£Ê½¡¹£¬ÇÒÊÇÕë¶Ô FD_ACCEPT
Õâ¸öʼþ£¬ËùÒÔµ± Client À´Á¬½Óʱ£¬ÎÒÃÇ Server ¶ËµÄ hwnd Õâ¸öÊÓ´°»áÊÕµ½
Winsock Stack ËÍÀ´µÄÒ»¸ö ASYNC_EVENT µÄѶϢ¡££¨²Î¼ûÇ°Ãæ WSAAsyncSelect
µÄÉ趨£©

Õâʱ£¬ÎÒÃÇÓ¦¸ÃÏÈÀûÓàWSAGETSELECTERROR(lParam) À´¼ì²éÊÇ·ñÓдíÎó£»
²¢ÓÉ WSAGETSELECTEVENT(lParam) µÃÖªÊÇʲ÷áʼþ·¢Éú£¨ÒòΪ
WSAAsyncSelect º¯Ê½¿ÉÕë¶Ôͬһ¸ö socket Í¬Ê±É趨ºÜ¶àʼþ£¬µ«ÊÇÖ»ÓÃÒ»¸öѶϢ
À´´ú±í£©£¨´Ë´¦µ±È»ÊÇ FD_ACCEPT Ê¼þ£©£»È»ááÔÙºô½ÐÏà¹ØµÄº¯Ê½À´´¦Àí´ËÒ»ÊÂ
¼þ¡£ËùÒÔÎÒÃǺô½Ð accept() º¯Ê½À´½¨Á¢ Server ¶ËµÄÁ¬½Ó¡£

accept()£º½ÓÊÜijһ Socket µÄÁ¬½ÓÒªÇó£¬ÒÔÍê³É Stream Socket µÄÁ¬½Ó¡£
¸ñ  Ê½£º SOCKET PASCAL FAR accept( SCOKET s, struct sockaddr FAR  *addr,        
                        int FAR *addrlen );
²Î  Êý£º        s       SocketµÄʶ±ðÂë
                addr    ´æ·ÅÀ´Á¬½ÓµÄ±Ë¶ËµÄλַ
                addrlen addrµÄ³¤¶È
´«»ØÖµ£º³É¹¦ - ÐµÄSocketʶ±ðÂë
        Ê§°Ü - INVALID_SOCKET (ºô½Ð WSAGetLastError() ¿ÉµÃÖªÔ­Òò)
˵Ã÷£º Server ¶ËÖ®Ó¦ÓóÌʽºô½Ð´ËÒ»º¯Ê½À´½ÓÊÜ Client ¶ËÒªÇóÖ® Socket Á¬½Ó¶¯
×÷£»Èç¹ûServer ¶ËÖ® Socket ÊÇΪ Blocking Ä£Ê½£¬ÇÒûÓÐÈËÒªÇóÁ¬½Ó¶¯×÷£¬ÄÇ÷á´ËÒ
º¯Ê½»á±» Block ×¡£»Èç¹ûΪ Non-Blocking Ä£Ê½£¬´Ëº¯Ê½»áÂíÉϻظ²´íÎó¡£accept()
º¯Ê½µÄ´ð¸²ÖµÎªÒ»ÐµĠSocket£¬´Ëн¨Ö® Socket ²»¿ÉÔÙÓÃÀ´½ÓÊÜÆäËüµÄÁ¬½ÓÒªÇó£»
µ«ÊÇÔ­ÏȼàÌýÖ® Socket ÈԿɽÓÊÜÆäËûÈ˵ÄÁ¬½ÓÒªÇó¡£

TCP socket µÄ Server ¶ËÔÚºô½Ð accept() áᣬ»á´«»ØÒ»¸öеĠsocket ºÅÂ룻¶øÕâ
¸öеĠsocket ºÅÂë²ÅÊÇÕæÕýÓë Client ¶ËÏàͨµÄ socket¡£±ÈÈç˵£¬ÎÒÃÇÓàsocket() ½¨
Á¢ÁËÒ»¸ö TCP socket£¬¶ø´Ë socket µÄºÅÂ루ϵͳ¸øµÄ£©Îª 1£¬È»ááÎÒÃǺô½ÐµÄ
bind()¡¢listen()¡¢accept() ¶¼ÊÇÕë¶Ô´ËÒ» socket£»µ±ÎÒÃÇÔÚºô½Ð accept()
áᣬ´«»ØÖµÊÇ
ÁíÒ»¸ö socket ºÅÂ루ҲÊÇϵͳ¸øµÄ£©£¬±ÈÈç˵ 3£»ÄÇ÷áÕæÕýÓë Client ¶ËÁ¬½ÓµÄÊǺÅ
Âë 3 Õâ¸ö socket£¬ÎÒÃÇÊÕËÍ×ÊÁÏÒ²¶¼ÊÇÒªÀûÓàsocket 3£¬¶ø²»ÊÇ socket 1£»¶ÁÕß²»¿É
¸ã´í¡£

ÎÒÃÇÔÚ³ÌʽÖжԠaccept() µÄºô½ÐÈçÏ£»ÎÒÃDz¢¿ÉÓɵڶþ¸ö²ÎÊýµÄ´«»ØÖµ£¬µÃÖª
¾¿¾¹ÊÇÄÄÒ»¸ö IP Î»Ö·¼° port ºÅÂëµÄ Client ÓëÎÒÃÇ Server Á¬½Ó¡£

struct sockaddr_in sa;
int    sa_len = sizeof(sa);
my_sd = accept(listen_sd, (struct sockaddr far *)&sa, &sa_len)

µ± Server ¶Ëºô½ÐÍê accept() áᣬÖ÷´Ó¼Ü¹¹µÄ TCP socket Á¬½Ó²ÅËãÕæÕý½¨Á¢Íê
±Ï£» Server ¼° Client ¶ËÒ²¾Í¿ÉÒÔ·Ö±ðÀûÓôËÒ» socket À´ËÍ×ÊÁϵ½¶Ô·½»òÊÕ¶Ô·½ËÍÀ´
µÄ×ÊÁÏÁË¡££¨ÓйØ×ÊÁϵÄÊÕËÍ£¬ÎÒÃǵÈÏÂÒ»ÆÚÔÙ̸£©


(ͼ 4) demoserv Óë democlnt ÔÚ WinKing ÉÏÁ¬½Ó³É¹¦áá״̬

¡¾Server ¼° Client ¶Ë½áÊø socket Á¬½Ó¡¿

×îááÎÒÃÇÀ´¿´Ò»ÏÂÈçºÎ½áÊø socket µÄÁ¬½Ó¡£socket µÄ¹Ø±ÕºÜ¼òµ¥£¬¶øÇÒ¿ÉÓÉ
Server »ò Client µÄÈÎÒ»¶ËÏÈÆô¶¯£¬Ö»Òªºô½Ð closesocket() ¾Í¿ÉÒÔÁË¡£¶øÒª¹Ø±Õ¼àÌý
״̬µÄ socket£¬Í¬ÑùÒ²ÊÇÀûÓôËÒ»º¯Ê½¡£

closesocket()£º¹Ø±ÕijһSocket¡£
¸ñ  Ê½£º int PASCAL FAR closesocket( SOCKET s );
²Î  Êý£º s         Socket µÄʶ±ðÂë
´«»ØÖµ£º ³É¹¦ - 0
        Ê§°Ü - SOCKET_ERROR (ºô½Ð WSAGetLastError() ¿ÉµÃÖªÔ­Òò)
˵Ã÷£º ´ËÒ»º¯Ê½ÊÇÓÃÀ´¹Ø±Õijһ Socket¡£
 ÈôÊÇʹÓÃÕßÔ­ÏȶÔÒª¹Ø±ÕÖ® Socket É趨 SO_DONTLINGER£¬ÔòÔÚºô½Ð´ËÒ»º¯Ê½
áᣬ»áÂíÉϻظ²£¬µ«ÊÇ´ËÒ» Sokcet ÉÐδ´«ËÍÍê±ÏµÄ×ÊÁÏ»á¼ÌÐøËÍÍêáá²Å¹Ø±Õ¡£
ÈôÊÇʹÓÃÕßÔ­ÏÈÉ趨´Ë Socket Îª SO_LINGER£¬ÔòÓÐÁ½ÖÖÇé¿ö£º
(a) Timeout ÉèΪ 0 µÄ»°£¬´ËÒ» Socket ÂíÉÏÖØÐÂÉ趨 (reset)£¬Î´´«Íê»òδÊÕµ½µÄ
×ÊÁÏÈ«²¿ÒÅʧ¡£
(b) Timeout ²»Îª 0 µÄ»°£¬Ôò»á½«×ÊÁÏËÍÍ꣬»òÊǵȵ½ Timeout ·¢Éúáá²ÅÕæÕý¹Ø
±Õ¡£

³Ìʽ½áÊøÇ°£¬¶ÁÕßÃÇ¿ÉǧÍò±ðÍüÁËÒªºô½Ð WSACleanup() À´Í¨Öª Winsock
Stack£»Èç¹ûÄú²»ºô½Ð´ËÒ»º¯Ê½£¬Winsock Stack ÖÐÓÐЩ×ÊÔ´¿ÉÄÜÈԻᱻÄúÕ¼ÓöøÎÞ
·¨Çå³ýÊÍ·ÅÓ´¡£

WSACleanup()£º½áÊø Windows Sockets DLL µÄʹÓá£
¸ñ  Ê½£º int PASCAL FAR WSACleanup( void );
²Î  Êý£º ÎÞ
´«»ØÖµ£º        ³É¹¦ - 0
        Ê§°Ü - SOCKET_ERROR (ºô½Ð WSAGetLastError() ¿ÉµÃÖªÔ­Òò)
˵Ã÷£º Ó¦ÓóÌʽÔÚʹÓàWindows Sockets DLL Ê±±ØÐëÏȺô½Ð
WSAStartup() À´Ïò Windows Sockets DLL ×¢²á£»µ±Ó¦ÓóÌʽ²»ÔÙÐèҪʹÓÃ
Windows  Sockets DLL Ê±£¬Ðëºô½Ð´ËÒ»º¯Ê½À´×¢ÏúʹÓã¬ÒÔ±ãÊÍ·ÅÆäÕ¼ÓõÄ×Ê
Ô´¡£

¡¾½áÓï¡¿

ÕâÆÚ±ÊÕßÏȽéÉÜÖ÷´Ó¼Ü¹¹ TCP sockets µÄÁ¬½Ó¼°¹Ø±Õ£¬ÒÔáá»áÔÙ½Ðø½éÉÜÈçºÎ
ÊÕËÍ×ÊÁÏ£¬ÒÔ¼°ÆäËû API µÄʹÓá£ÏëÒª½øÒ»²½Á˽âÈçºÎ׫д Winsock ³ÌʽµÄ¶ÁÕߣ¬
¿ÉÒԺúÃÑо¿Ò»Ï±ÊÕß demoserv ¼° democlnt ÕâÁ½¸ö³Ìʽ£»Ò²Ðí²»ÊÇдµÄºÜºÃ£¬µ«
ÊÇÏ£Íû¿ÉÒÔ´ø¸ø²»¶® Winsock ³ÌʽÉè¼ÆµÄÈËÒ»¸öÆ𲽡£

¶ÁÕßÃÇÒà¿É×ÔÐÐÓàanonymous ftp ·½Ê½µ½ SEEDNET Ì¨±±Ö÷»ú tpts1.seed.net.tw
£¨139.175.1.10£©µÄ UPLOAD / WINKING Ä¿Â¼Ï£¬È¡µÃ±ÊÕßÓë³Â½¨ÁæС½ãËùÉè¼ÆµÄ
WinKing Õâ¸ö Winsock Stack µÄÊÔÓð棬À´ÅÜ demoserv Óë democlnt ÕâÁ½¸ö³Ìʽ¼°Æä
ËûÐíÐí¶à¶àµÄ Winsock Ó¦ÓóÌʽ¡££¨Õýʽ°æ±¾ÇëÇ¢ SEEDNET ·þÎñÖÐÐÄ£¬Ð°æµÄ
WinKing ÒѺ¬ Windows ²¦½Ó¼° PPP ³Ìʽ£¬Êʺϵ绰²¦½ÓÓû§ÔÚ Windows »·¾³ÏÂʹ
ÓàSEEDNET£»WinKing Í¬ÑùÒ²Ìṩ Ethernet »·¾³µÄʹÓᣣ©

--
¡ù À´Ô´:£®°×ɽºÚË® bbs.neu.edu.cn£®[FROM: beaver]

--
¡ù À´Ô´:¡¤¹þ¶û±õ×϶¡ÏãÕ¾ bbs1.hit.edu.cn¡¤[FROM: bbs@conger.neu.edu.c] 
[°Ù±¦Ïä] [·µ»ØÊ×Ò³] [Éϼ¶Ä¿Â¼] [¸ùĿ¼] [·µ»Ø¶¥²¿] [Ë¢ÐÂ] [·µ»Ø]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
Ò³ÃæÖ´ÐÐʱ¼ä£º208.077ºÁÃë