zoukankan      html  css  js  c++  java
  • 客户端升级为select网路模型

    服务器端:

    #include<WinSock2.h>
    #include<Windows.h>
    #include<vector>
    #include<stdio.h>
    #include<iostream>
    
    
    #pragma comment(lib,"ws2_32.lib")
    
    enum CMD { CMD_Login, CMD_Login_Result, CMD_Logout, CMD_Logout_Result, CMD_New_User_Join, CMD_ERROR };
    
    //包头
    struct DataHeader
    {
        short dataLength;
        short cmd;
    };
    //包体
    struct Login:public DataHeader
    {
        Login()
        {
            dataLength = sizeof(Login);
            cmd = CMD_Login;
        }
        char username[32];
        char password[32];
    };
    
    struct LoginResult :public DataHeader
    {
        LoginResult()
        {
            dataLength = sizeof(LoginResult);
            cmd = CMD_Login_Result;
            result = 0;
        }
        int result;
    };
    
    struct Logout :public DataHeader
    {
        Logout()
        {
            dataLength = sizeof(Logout);
            cmd = CMD_Logout;
        }
        char username[32];
    };
    
    struct LogoutResult :public DataHeader
    {
        LogoutResult()
        {
            dataLength = sizeof(LogoutResult);
            cmd = CMD_Logout_Result;
            result = 0;
        }
        int result;
    };
    
    struct NewUserJoin :public DataHeader
    {
        NewUserJoin()
        {
            dataLength = sizeof(NewUserJoin);
            cmd = CMD_New_User_Join;
            sock = 0;
        }
        int sock;
    };
    
    std::vector<SOCKET> g_client;
    
    int process_solve(SOCKET _cSOCK)
    {
        //增加一个缓冲区
        char szRecv[1024] = {};
        //5.接收客户端新数据
        int nLen = recv(_cSOCK, szRecv, sizeof(DataHeader), 0);
        DataHeader *header = (DataHeader*)szRecv;
    
        if (nLen <= 0)
        {
            printf("客户端已退出!任务结束!");
            return -1;
        }
        switch (header->cmd){
        case CMD_Login:
        {
            recv(_cSOCK, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
            Login *login = (Login*)szRecv;
            printf("收到客户端<Socket=%d>请求:CMD_Login,数据长度:%d
    UserName:%s
    PassWord:%s
    ", _cSOCK,login->dataLength, login->username, login->password);
            //忽略判断用户密码是否正确的过程
            LoginResult ret;
            send(_cSOCK, (char *)&ret, sizeof(LoginResult), 0); //再发消息体
    
        }
        case CMD_Logout:
        {
    
            recv(_cSOCK, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
            Logout* logout = (Logout*)szRecv;
            printf("收到命令:CMD_Logout,数据长度:%d
    UserName:%s
    ", logout->dataLength, logout->username);
    
            //忽略判断用户密码是否正确的过程
            LogoutResult let;
            send(_cSOCK, (char *)&let, sizeof(let), 0); //再发消息体
        }
            break;
        case CMD_New_User_Join:
        {
    
            recv(_cSOCK, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
            NewUserJoin* UserJoin = (NewUserJoin*)szRecv;
            printf("收到命令:CMD_Logout,数据长度:%d
    UserName:%s
    ", UserJoin->dataLength);
    
            //忽略判断用户密码是否正确的过程
            NewUserJoin let;
            send(_cSOCK, (char *)&let, sizeof(let), 0); //再发消息体
        }
            break;
        default:
        {
                   DataHeader header = { 0 };
                   send(_cSOCK, (char *)&header.cmd, sizeof(header), 0);
        }
    
            break;
        }
    }
    
    int main()
    {
        
        WORD ver = MAKEWORD(2, 2);
        WSADATA dat;
        //WinSocket启动
        WSAStartup(ver, &dat);
    
        //1、建立一个socket
        SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //AF_INET创建一个IPV4的套接字,SOCK_STREAM面向数据流的,IPPROTO_TCP TCP
        if (INVALID_SOCKET == _sock)
        {
            printf("ERROR:建立失败!
    ");
        }
        //2.绑定
        sockaddr_in _sin = {};     //创建网络地址
        _sin.sin_family = AF_INET;
        _sin.sin_port = htons(4567); //Host to Network Short
        _sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // IP地址 
        if (bind(_sock, (sockaddr *)&_sin, sizeof(_sin)) == SOCKET_ERROR)
        {
            printf("ERROR:绑定失败!
    ");
        }
        else
        {
            printf("服务器端绑定成功......
    ");
        }
        //3.监听网络端口
        if (listen(_sock, 5) == SOCKET_ERROR)//第二个参数为最大等待多少人可以同时连接
        {
            printf("ERROR:监听失败!
    ");
        }
        else
        {
            printf("服务器端监听成功......
    ");
        }
        
        while (1)
        {
            //伯克利 socket
            fd_set fd_Read;
            fd_set fd_Write;
            fd_set fd_Exp;
            
            FD_ZERO(&fd_Read);//FD_ZERO 清空集合里的数据
            FD_ZERO(&fd_Write);
            FD_ZERO(&fd_Exp);
    
            FD_SET(_sock, &fd_Read);//FD_SET 可以进行操作的宏
            FD_SET(_sock, &fd_Write);
            FD_SET(_sock, &fd_Exp);
    
            for (int n = g_client.size() - 1; n >= 0; n--)
            {
                FD_SET(g_client[n], &fd_Read);
            }
    
            /*
            select(
                _In_ int nfds,
                _Inout_opt_ fd_set FAR * readfds,
                _Inout_opt_ fd_set FAR * writefds,
                _Inout_opt_ fd_set FAR * exceptfds,
                _In_opt_ const struct timeval FAR * timeout
            );
            */
    
            //nfds是一个整数值,是指fd_set集合所有的描述符(select里的第一个参数)的范围(而不是数量)
            //既是所有文件描述符最大值+1
            timeval t = {1,0};
    
            int ret = select(_sock + 1, &fd_Read, &fd_Write, &fd_Exp, &t);
            if (ret < 0)
            {
                printf("select任务结束!
    ");
                break;
            }
            if (FD_ISSET(_sock, &fd_Read))
            {
                FD_CLR(_sock, &fd_Read);
                //4.等待接收客户端连接
                sockaddr_in clientAddr = {};
                int nAddrLen = sizeof(sockaddr_in);
                SOCKET _cSOCK = INVALID_SOCKET;
    
                _cSOCK = accept(_sock, (sockaddr *)&clientAddr, &nAddrLen);
                if (_cSOCK == INVALID_SOCKET)
                {
                    printf("ERROR:无效客户端SOCKET!
    ");
                }
                for (int n = g_client.size() - 1; n >= 0; n--)
                {
                    NewUserJoin UserJoin;
                    send(g_client[n], (const char*)&UserJoin, sizeof(UserJoin), 0);
                }
    
                g_client.push_back(_cSOCK);
                printf("新客户端加入:Socket=%d,IP = %s
    ", (int)_cSOCK, inet_ntoa(clientAddr.sin_addr));//inet_ntoa(clientAddr.sin_addr)将接收到的IP地址转化为字符串
                
                
            }
            for (int n = 0; n < fd_Read.fd_count; n++)
            {
                if (process_solve(fd_Read.fd_array[n]) == -1)
                {
                    auto iter = find(g_client.begin(), g_client.end(), process_solve(fd_Read.fd_array[n]));
                    if (iter != g_client.end())
                    {
                        g_client.erase(iter);
                    }
                }
            }
            printf("空闲时间处理其他业务.......
    ");
        }
    
        for (int n = g_client.size(); n >= 0; n--)
        {
            //8.关闭自身的socket
            closesocket(g_client[n]);
        }
    
        //8.关闭自身的socket
        closesocket(_sock);
    
        //WinSocket关闭
        WSACleanup();
    
        system("pause");
        return 0;
    }

    客户端:

    #include<WinSock2.h>
    #include<Windows.h>
    #include<stdio.h>
    
    #pragma comment(lib,"ws2_32.lib")
    
    enum CMD { CMD_Login, CMD_Login_Result, CMD_Logout, CMD_Logout_Result, CMD_New_User_Join, CMD_ERROR };
    
    //包头
    struct DataHeader
    {
        short dataLength;
        short cmd;
    };
    //包体
    struct Login :public DataHeader
    {
        Login()
        {
            dataLength = sizeof(Login);
            cmd = CMD_Login;
        }
        char username[32];
        char password[32];
    };
    
    struct LoginResult :public DataHeader
    {
        LoginResult()
        {
            dataLength = sizeof(LoginResult);
            cmd = CMD_Login_Result;
            result = 0;
        }
        int result;
    };
    
    struct Logout :public DataHeader
    {
        Logout()
        {
            dataLength = sizeof(Logout);
            cmd = CMD_Logout;
        }
        char username[32];
    };
    
    struct LogoutResult :public DataHeader
    {
        LogoutResult()
        {
            dataLength = sizeof(LogoutResult);
            cmd = CMD_Logout_Result;
            result = 0;
        }
        int result;
    };
    
    struct NewUserJoin :public DataHeader
    {
        NewUserJoin()
        {
            dataLength = sizeof(LogoutResult);
            cmd = CMD_New_User_Join;
            sock = 0;
        }
        int sock;
    };
    
    int process_solve(SOCKET _cSOCK)
    {
        //增加一个缓冲区
        char szRecv[1024] = {};
        //5.接收客户端新数据
        int nLen = recv(_cSOCK, szRecv, sizeof(DataHeader), 0);
        DataHeader *header = (DataHeader*)szRecv;
    
        if (nLen <= 0)
        {
            printf("与服务器断开连接!任务结束!");
            return -1;
        }
        switch (header->cmd){
            case CMD_Login_Result:
            {
                    recv(_cSOCK, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
                    LoginResult *loginresult = (LoginResult*)szRecv;
                    printf("收到服务端消息请求:CMD_Login_Result,数据长度:%d
    UserName:%s
    PassWord:%s
    ", loginresult->dataLength);
    
            }
            break;
            case CMD_Logout_Result:
            {
    
                    recv(_cSOCK, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
                    LogoutResult* logoutresult = (LogoutResult*)szRecv;
                    printf("收到服务端消息请求:CMD_Logout_Result,数据长度:%d
    UserName:%s
    ", logoutresult->dataLength);
    
            }
            break;
            case CMD_New_User_Join:
            {
                    recv(_cSOCK, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
                    NewUserJoin* newuserjoin = (NewUserJoin*)szRecv;
                    printf("收到服务端消息请求:CMD_New_User_Join,数据长度:%d
    UserName:%s
    ", newuserjoin->dataLength);
            }
            break;
        }
    }
    
    int main()
    {
        WORD ver = MAKEWORD(2, 2);
        WSADATA dat;
        WSAStartup(ver, &dat);
    
        //1.建立一个socket
        SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (INVALID_SOCKET == _sock)
        {
            printf("ERROR:建立失败!
    ");
        }
        else{
            printf("客户端绑定成功......
    ");
        }
        //2.连接服务器
        sockaddr_in _sin = {};     //创建网络地址
        _sin.sin_family = AF_INET;
        _sin.sin_port = htons(4567); //Host to Network Short
        _sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//inet_addr("127.0.0.1"); // IP地址 
        int ret = connect(_sock, (sockaddr *)&_sin, sizeof(sockaddr_in));
        if (SOCKET_ERROR == ret)
        {
            printf("ERROR:连接失败!
    ");
        }
        else
        {
            printf("客户端连接成功......
    ");
        }
    
        while (true)
        {
            //伯克利 socket
            fd_set fd_Read;
            FD_ZERO(&fd_Read);//FD_ZERO 清空集合里的数据
            FD_SET(_sock, &fd_Read);//FD_SET 可以进行操作的宏
            timeval t = {1,0};
            int ret = select(_sock, &fd_Read, 0, 0,&t);
            if (ret < 0)
            {
                printf("select任务结束1!");
                break;
            }
            if (FD_ISSET(_sock,&fd_Read))
            {
                FD_CLR(_sock, &fd_Read);
                
                if (process_solve(_sock) == -1)
                {
                    printf("select任务结束2!");
                    break;
                }
            }
            printf("空闲时间处理其他业务.......
    ");
            Login login;
            strcpy(login.username, "sutaoyu");
            strcpy(login.password, "sutaoyu01");
            send(_sock, (const char*)&login, sizeof(Login),0);
            Sleep(1000);
        }
    
        
        //7.关闭套接字
        closesocket(_sock);
    
        //WinSocket启动
        WSAStartup(ver, &dat);
    
    
    
        //WinSocket关闭
        WSACleanup();
        printf("已退出!");
        getchar();
        return 0;
    }
  • 相关阅读:
    使用Yeoman搭建 AngularJS 应用 (9) —— 让我们搭建一个网页应用
    advance shading——菲涅耳现象
    现代编译原理--第六章(中间树 IR Tree 含源码)
    现代编译原理--第五章(活动记录)
    现代编译原理--第四章(语义分析以及源码)
    现代编译原理--第三章(抽象语法树以及源码)
    现代编译原理--第二章(语法分析之LL(K))
    现代编译原理--第一章(词法分析)
    advance shading--BRDF
    个人作业——软件工程实践总结作业
  • 原文地址:https://www.cnblogs.com/zhuifeng-mayi/p/10999752.html
Copyright © 2011-2022 走看看