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模型

你可能感兴趣的:(SOC)