注册 登录
编程论坛 VC++/MFC

(分享)winsock 编程基础 之 阻塞 I/O 模型

funyh250 发布于 2014-06-22 18:02, 586 次点击
程序代码:
    WSAData wsaDate;                                    //声明一个WSADate结构体(包含了Winsock库的版本信息)变量
    int nRet=WSAStartup(MAKEWORD(2,2),&wsaDate);          //初始化该结构体(协商版本) 若返回0则成功
   
//if(nRet!=0)
   
//错误处理
    sockaddr_in saServer;                                //声明一个地址结构体 sockaddr是系统自己使用的
    saServer.sin_family=AF_INET;                       //必须是AF_INET
    saServer.sin_port=htons(10000);                   //必须转换成网络字节序 htonl/htons (host to net long/ short)
    saServer.sin_addr.s_addr=htonl(INADDR_ANY);        //接收任意IP的数据 (通配地址)               //数字是short 字符long
    SOCKET sasocket;                                  //声明一个套接字句柄变量
    sasocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//使用UDP时的参数SOCK_DGRAM IPPROTO_UDP

    bind(sasocket,(sockaddr*)&saServer,sizeof(saServer));//绑定成功返回0  否则SOCK_ERROR
    listen(sasocket,1);//backlog表示可以接受的客服请求的最大数量 监听成功返回0  SOCK_ERROR

    sockaddr_in saClient;                             //客服端的地址结构体
    int nsaClient=sizeof(sockaddr);                     //客服端地址信息的大小
    SOCKET hClientsocket=accept(sasocket,(sockaddr*)&saClient,&nsaClient);//接收客服端的连接请求
                                                      
//返回的套接字将用于与这个客服的连接  sasocket可以继续接受其他客服请求
                                                      
//如果请求队列为空 那么将被阻塞 失败返回INVALID_SOCKET

    const int buff_len=1024;
    char recvbuff[buff_len+1];
    nRet=recv(hClientsocket,recvbuff,buff_len,0);//返回接收数据的实际大小 失败返回SOCKET_ERROR flags参数有MSG_PEEK MSG_OOB 或一起使用
   
//如果系统能接收的最大数据量为len 那么recv将返回len 但不能超过buff_len
   
//如果系统缓存区满了 那么调用recv的线程将被阻塞(停止运行) ,直到系统可以接收数据

   
//************确保接收(发送)全部数据********************************************************
    int nbuff_len=520;//假设要接受的数据大小为520                                   
    int nn=0;                                                                       
    while(nbuff_len>0)                                                              
    {                                                                              
        int ret=recv(hClientsocket,&recvbuff[nn],nbuff_len,0);                     
                                       //nn在增加  nbuff_len在递减                  
        if(ret=SOCKET_ERROR)       //发送失败 就这一种情况                          
        {                                                                           
            //错误处理                                                              
        }                                                                        
        else                                                                       
            if(ret==0)                                                            
            {                                                                       
                //连接被发送方关闭,错误处理                                          
            }                                                                       
            nn+=ret;                                                               
            nbuff_len-=ret;                                                        
    }                                                                              
    //**********************************************************************************************

    int nSend=send(hClientsocket,recvbuff,nRet,0);//把接收到的实际数据的大小发送出去 flags参数有MSG_DONTROUTE MSG_OOB 或一起使用
   
//nRet不能超过系统接收的最大长度            SOCKET_ERROR
   
//

    shutdown(hClientsocket,SD_SEND);//SOCKET_ERROR  如果是UDP 此操作不需要 因为每次发送(接收)的都是完整的数据报
   
//shutdown之后还在接收数据
   
//do
   
//{              数据流还在流向接收端直到全部到达
   
//ret=recv(hClientsocket,&recvbuff[nn],nbuff_len,0);
   
//}while(ret!=0)
   
//如果ret==0了
    closesocket(hClientsocket);//SOCKET_ERROR
    WSACleanup();//清除关于winsock的一切资源


学习笔记分享下
1 回复
#2
yuccn2014-06-23 13:54
1