WinSock编程基础

一、套接字模式

  1、阻塞模式

      创建套接字时,默认是阻塞模式,对recv函数调用会使程序进入等待状态,知道接收到数据才返回。

  2、非阻塞模式:

     可以调用ioctlsocket函数显式地让套接字工作在非阻塞模式下。

u_long ul = 1;
    SOCKET s = ::socket(AF_INET,SOCK_STREAM,0);
    ::ioctlsocket(s,FIONBIO,(u_long*)&ul);

3、windows提供的I/O模型

    1、Select模型

           使用select函数来管理I/O

#include "../../common/InitSock.h"
#include <stdio.h>

CInitSock initsock;

int main(){
    
    USHORT nPort = 4567;
    SOCKET sListen = ::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(nPort);
    sin.sin_addr.S_un.S_addr = INADDR_ANY; //服务端一般这样这是地址

    //绑定套接字到本地机器
    if(::bind(sListen,(sockaddr*)&sin,sizeof(sin)) == SOCKET_ERROR){
        printf("Failed bind()\n");
        return -1;
    }

    //进入监听模式
    ::listen(sListen,5);

    //select模型处理过程
    //1)初始化一个套接字fdsocket,添加监听套接字句柄到这个集合
    fd_set fdsocket;  //所有可用套接字集合
    FD_ZERO(&fdsocket);
    FD_SET(sListen,&fdsocket);

    while(TRUE){
        //2)将fdsocket集合的一个拷贝fdRead传递给select函数
        //  当有事情发生时,select函数移除fdRead集合中没有未决I/O操作的套接字句柄,然后返回
        fd_set fdRead = fdsocket;
        int nRet = ::select(0,&fdRead,NULL,NULL,NULL);
        if(nRet > 0){
            //3)通过将原来fdsocket集合与select处理过的fdread集合比较
            //  确定有哪些套接字有未决I/O, 并进一步处理这些I/O
            for (int i = 0; i != (int)fdsocket.fd_count; ++i)
            {
                if(FD_ISSET(fdsocket.fd_array[i],&fdRead)){
                    if(fdsocket.fd_array[i] == sListen){//(1)监听套接字接收到新连接
                        if(fdsocket.fd_count < FD_SETSIZE){
                            sockaddr_in addrRemote;
                            int nAddrLen = sizeof(addrRemote);
                            SOCKET sNew = ::accept(sListen,(SOCKADDR*)&addrRemote,&nAddrLen);
                            FD_SET(sNew,&fdsocket);
                            printf("接收到连接%s\n",::inet_ntoa(addrRemote.sin_addr));
                        }else{
                            printf("too much connections!\n");
                            continue;
                        }
                    }else{
                        char szText[256];
                        int nRecv = ::recv(fdsocket.fd_array[i],szText,strlen(szText),0);//可读
                        if(nRecv > 0){
                            szText[nRecv] = '\n';
                            printf("接收到数据:%s",szText);
                        }else{ //连接关闭 重启或中断
                            ::closesocket(fdsocket.fd_array[i]);
                            FD_CLR(fdsocket.fd_array[i],&fdsocket);
                        }
                    }
                }
            }
        }else{
            printf("Failed select()\n");
            break;
        }
    }
    
    return 0;
}

   

    2、WSAAsyncSelect模型

        WSAAsyncSelect模型允许应用程序以windows消息的形式接受到网络时间通知。 MFC的CSocket也是该模型。

        (为适应windows的消息驱动环境而设置的,现在许多对性能要求不高的网络应用程序都采用WSAASyncSelect模型)

    3、WSAEventSelect模型

    4、重叠(Overlapped)I/O模型

posted @ 2015-03-27 16:32  hongjack  阅读(503)  评论(0编辑  收藏  举报