Cpp-Socket网络编程(六)将多次收发报文数据升级为一次收发

1. 为命令CMD的枚举增加两个成员:

enum CMD {
    CMD_LOGIN,
    CMD_LOGIN_RESULT,
    CMD_LOGOUT,
    CMD_LOGOUT_RESULT,
    CMD_ERROR
};

2. 使用继承的方式,令Login/Logout/LoginResult/LogoutResult结构体继承于DataHeader,并在Login的构造函数里为cmd和dataLength赋值,这样就不必在定义消息时将DataHeader单独写一遍,也可以避免出错。

//包头
struct DataHeader {
    short dataLength; //数据长度
    short cmd; //命令
};

//包体 DataPackage
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 = 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 = 0;
    }
    int result;
};

3. 修改服务器端消息的解析方式

switch (header.cmd) {
            case CMD_LOGIN:
            {
                Login login = {};
                //接收客户端的登陆信息,这里要注意除去headerd部分,因此要加上数据偏移,并且读取范围要减去header的大小
                recv(_cSock, (char*)&login + sizeof(DataHeader), sizeof(Login) - sizeof(DataHeader), 0); 
                printf("receive message: CMD_LOGIN, data length:%d, username:%s, password: %s\n", login.dataLength, login.UserName, login.PassWord); //提示收到命令
                //假设用户输入正确(这里忽略用户名和密码是否正确的验证过程)
                LoginResult inret;
                //7. 向客户端发送数据send
                send(_cSock, (char*)&inret, sizeof(LoginResult), 0); //向客户端发送登陆结果
            }
            break;
            case CMD_LOGOUT:
            {
                LogOut logout = {};
                //接收客户端的登出信息,这里要注意除去headerd部分,因此要加上数据偏移,并且读取范围要减去header的大小
                recv(_cSock, (char*)&logout + sizeof(DataHeader), sizeof(LogOut) - sizeof(DataHeader), 0);
                printf("receive message: CMD_LOGIN, data length:%d, username:%s\n", logout.dataLength, logout.UserName);
                LogoutResult outret;
                //7. 向客户端发送数据send
                send(_cSock, (char*)&outret, sizeof(LogoutResult), 0);
            }
            break;
            default:
                header.cmd = CMD_ERROR;
                header.dataLength = 0;
                send(_cSock, (char*)&header, sizeof(DataHeader), 0);
            break;
        }

4. 修改客户端的消息处理方式

while (true) {
        //3. 用户输入请求命令
        scanf("%s", cmdBuf);
        //4. 处理请求命令
        if (0 == strcmp(cmdBuf, "exit")) {
            printf("receive quit message!");
            break;
        } else if (0 == strcmp(cmdBuf, "login")){
            //5. 向服务器端发送请求
            Login login;
            strcpy(login.UserName, "liu");
            strcpy(login.PassWord, "1234");
            send(_sock, (const char*)&login, sizeof(Login), 0);
            //6. 接收服务器返回数据
            LoginResult loginRet = {};
            recv(_sock, (char*)&loginRet, sizeof(LoginResult), 0);
            printf("LoginResult: %d\n", loginRet.result);
            
        } else if (0 == strcmp(cmdBuf, "logout")) {
            //5. 向服务器端发送请求
            LogOut logout;
            strcpy(logout.UserName, "liu");
            send(_sock, (const char*)&logout, sizeof(LogOut), 0);
            //6. 接收服务器返回数据
            LogoutResult logoutRet = {};
            recv(_sock, (char*)&logoutRet, sizeof(LogoutResult), 0);
            printf("LogoutResult: %d\n", logoutRet.result);
            
        } else {
            printf("unsupported command!");
        }
    }

5. 实验结果

connect5

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值