TCP-事件模型

#include "main.h"

VOID Server_write_error()
{

}


/*1.打开网络库
* 2.校验网络库版本
* 3.创建SOCKET
* 4.绑定IP地址和端口
* 5.开始监听
* 6.创建客户端socket/接受链接
* 7.与客户端收发消息
* 8.(6.7)两步的函数accept,send,recv 有堵塞,可以用select解决,这种函数可以处理小型网络
*/
int create(const char* IpAdress)
{
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;

    /* 使用Windef.h中声明的MAKEWORD(低字节、高字节)宏 */
    wVersionRequested = MAKEWORD(2, 2);

    /*启用网络链接库,调用的封装库命令*/
    err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0) {
        /* Tell the user that we could not find a usable */
        /* Winsock DLL.                                  */
        printf("WSAStartup failed with error: %d\n", err);
        return -1;
    }

    /*确认WinSock DLL支持2.2*/

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        /* Tell the user that we could not find a usable */
        /* WinSock DLL.                                  */
        printf("Could not find a usable version of Winsock.dll\n");
        //清理网络库
        WSACleanup();
        return -1;
    }


    //创建套接字。 创建网络类型 tcp或者upd
    SOCKET socketServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (INVALID_SOCKET == socketServer)
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_socket",ret.c_str(),  0);
        //清理网络库
        WSACleanup();
        return -1;
    }
    //设置sockaddr结构
    sockaddr_in saServer;
    saServer.sin_family = AF_INET;
    saServer.sin_addr.s_addr = INADDR_ANY;
    saServer.sin_port = htons(9999);



    // 绑定本机(服务器)IP和端口
    //sockaddr结构中的信息
    if (SOCKET_ERROR == bind(socketServer, (SOCKADDR*)&saServer, sizeof(saServer)))
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_bind", ret.c_str(),  0);
        //释放stocket
        closesocket(socketServer);
        //清理网络库
        WSACleanup();
        return -1;
    }

    /*监听本机(服务器)的套接字*/

    if (SOCKET_ERROR == listen(socketServer, SOMAXCONN))
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_listen", ret.c_str(),  0);
        //释放stocket
        closesocket(socketServer);
        //清理网络库
        WSACleanup();
        return -1;
    }


    fd_es_set setSockets;
    memset(&setSockets,0,sizeof(setSockets));


    /*创建一个套接字 事件*/
    HANDLE eventSerevr = WSACreateEvent();
    if (WSA_INVALID_EVENT == eventSerevr)
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_WSACreateEventServer", ret.c_str(),  0);
        //释放stocket
        closesocket(socketServer);
        //清理网络库
        WSACleanup();
        return -1;
    }

    /*将服务器socket和事件绑定*/
    if (SOCKET_ERROR == WSAEventSelect(socketServer, eventSerevr, FD_ACCEPT))
    {
        string ret = to_string(WSAGetLastError());
        MessageBoxA(0, "error_WSAEventSelecttServer", ret.c_str(), 0);
        //释放stocket
        closesocket(socketServer);
        //清理网络库
        WSACleanup();
        return -1;
    }

    /*将服务器socket和事件对象句柄写进结构体*/
    setSockets.sockall[setSockets.count] = socketServer;
    setSockets.eventall[setSockets.count] = eventSerevr;
    setSockets.count++;



    while (true)
    {   
        
        /*为了防止一个用户死循环访问服务器,造成事件一直处理同一个客户端,进行优化,循环遍历单个数组询问是否有事件信号*/
        /*同时WSAWaitForMultipleEvents函数参数一每次只能处理64个事件数组,而我们改成每次处理1个,循环处理变相能处理无穷多的事件了*/
        DWORD RET = 0;
        for (DWORD Index = 0; Index 

利用windows的网络事件函数,系统将自动用异步的方式帮我们查看socket消息,接收到消息后,我们将无序的查看接收到的消息(比如:我们有事件[5],先后接收到45321送来的消息,事件只能接收到12345发来了消息,并不能知道先后顺序,故只能按12345的顺序处理消息),而消息机制本质和事件差不多,区别就是消息机制由系统的消息队列记录先后顺序,会按45321的顺序处理,处理更合理

你可能感兴趣的:(tcp/ip,php,网络协议)