一个异步Socket通信的例子(Windows)

本文介绍在Windows环境下如何使用WSAEventSelect和WSAWaitForMultipleEvents方法实现Socket的异步编程,并提供了一个具体的编程示例,该示例演示了如何同时异步连接到百度和谷歌的主页。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Windows下面,使一个socket改成异步有两种方法。

 

(1)调用WSAAsyncSelect方法

(2)调用WSAEventSelect方法

 

 

对Socket进行轮寻可以使用Select函数,或者自己通过WSAWaitForMultipleEvents进行轮训,但WSAWaitForMultipleEvents有一个限制令人很苦恼,即WSAWaitForMultipleEventsWSAWaitForMultipleEvents在每个线程中最多只能监听64个Socket,如果需要监听更多的Socket,则需要启动多个线程;Select函数虽然也有Socket个数限制,但却是能最多监听1024个Socket,比WSAWaitForMultipleEvents多多了。WSAAsyncSelect方法需要有接受响应消息的窗口句柄;下面这个例子采用了WSAEventSelect和WSAWaitForMultipleEvents的方法下载网页的Socket编程,它采用异步Socket的方式从百度和谷歌下载首页。

 

 

#example.cpp

 

#include "stdafx.h"
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <winsock2.h>
#include <windows.h>
#include <winbase.h>
#include <io.h>

 

int _tmain(int argc, _TCHAR* argv[]){

 

      WSADATA     wsaData;        
      WSAStartup(0x0202, &wsaData);
     
      int  sock[2] ;

      int pos;
      unsigned int port=80;
      int res =0;
      char *str_robots= "GET /index.html HTTP/1.0/r/nHost: www.baidu.com /r/nUser-Agent: Test (Test@263.com)/r/n/r/n ";

     

      struct sockaddr_in server[2]; 
      char buf[10240]; 

      sock[0] = socket(AF_INET, SOCK_STREAM, 0); 
      sock[1] = socket(AF_INET, SOCK_STREAM, 0);

      server[0].sin_family = AF_INET; 
      server[0].sin_port = htons(port);
      server[0].sin_addr.S_un.S_addr = inet_addr( "119.75.213.61" ); //www.baidu.com

      server[1].sin_family = AF_INET; 
      server[1].sin_port = htons(port);
      server[1].sin_addr.S_un.S_addr = inet_addr( "64.233.189.104" ); //www.google.com

 

      WSAEVENT hEvent[2];
      hEvent[0]  = WSACreateEvent();
      hEvent[1]  = WSACreateEvent();
      WSANETWORKEVENTS events;
      WSAEventSelect(sock[0], hEvent[0], FD_READ|FD_WRITE|FD_CONNECT);
      WSAEventSelect(sock[1], hEvent[1], FD_READ|FD_WRITE|FD_CONNECT);

 

      connect(sock[0], (struct sockaddr*)&server[0], sizeof(server));

      connect(sock[1], (struct sockaddr*)&server[1], sizeof(server));

 

      int total = 2;

      

       while(total)
      {  

           res = WSAWaitForMultipleEvents(2, hEvent, FALSE, 10,FALSE); //WSA_INFINITE
           for(int i=0;i<2;i++){
               int result = WSAEnumNetworkEvents(sock[i],hEvent[i],&events);
               if( result == SOCKET_ERROR){
                    printf("Error /n");
                   break;
               }else if(result == WSA_WAIT_TIMEOUT){
                   continue;
              }else{
                  if(events.lNetworkEvents & FD_READ){
                       pos = 0;
                       count =0;
                       do{
                            count = recv(sock[i], buf+pos, 512, 0);
                            pos += count;
                       }while(count>0);
                       buf[pos] = '/0';
                       printf("buf = %s/n",buf);
                       total--;
                  }else if(events.lNetworkEvents & FD_WRITE){
                    send(sock[i],str_robots,strlen(str_robots),0);    
                  }//end if

              }//end if

          }//end for
     }//end while
 

 

return(0);

}

 

对于异步Socket,如果在Windows下面使用MFC的话,事情就变得容易多了,可以使用CAsyncSocket类,这个类封装了异步Socket请求的各种方法。

 

在Linux/Unix系统下编程,可以使用fnctl函数将一个Socket变成异步的,并且通过Select和Poll, epoll进行轮寻。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值