windows socket 完善数据简单结构化

client

//交互命令
enum CMD {
    CMD_LOGIN,
    CMD_LOGIN_RESULT,
    CMD_LOGOUT,
    CMD_LOGOUT_RESULT,
    CMD_ERROR
};
//消息头
struct DataHeader {
    int cmd;//消息指令
    int dataLength;//消息长度
};
//登录消息
struct Login : public DataHeader {
    Login() {
        cmd = CMD_LOGIN;
        dataLength = sizeof(Login);
    }
    char szName[64];//用户名
    char szPass[64];//密码
};
//登录返回消息
struct LoginResult : public DataHeader {
    LoginResult() {
        cmd = CMD_LOGIN_RESULT;
        dataLength = sizeof(LoginResult);
        iResult = 1;
    }
    int iResult;
};
//登出消息
struct Logout : public DataHeader {
    Logout() {
        cmd = CMD_LOGOUT;
        dataLength = sizeof(Logout);
    }
    char szName[64];
};
//登出返回消息
struct LogoutResult : public DataHeader {
    LogoutResult() {
        cmd = CMD_LOGOUT_RESULT;
        dataLength = sizeof(LogoutResult);
        iResult = 2;
    }
    int iResult;
};
//客户端完善结构化消息
int function08() {
    SOCKET sktCli = init("192.168.3.18", 8080);
    if (sktCli == INVALID_SOCKET) {
        return -1;
    }

    while (true) {
        char szCmd[64] = { 0 };
        scanf("%s", szCmd);
        if (strcmp(szCmd, "exit") == 0) {
            printf("[client] exit ...\n");
            break;
        }

        DataHeader dh = {0};
        if (strcmp(szCmd, "login") == 0) {
            Login login;
            strcpy(login.szName, "爱白菜的小昆虫登录");
            strcpy(login.szPass, "我不知道密码是啥");
            send(sktCli, (const char *)&login, sizeof(login), 0);
            LoginResult result;
            recv(sktCli, (char *)&result, sizeof(result), 0);
            printf("[server] cmd=%d dataLength=%d iResult=%d\n", result.cmd, result.dataLength, result.iResult);
        }
        else if(strcmp(szCmd, "logout") == 0){
            Logout logout;
            strcpy(logout.szName, "爱白菜的小昆虫退出");
            send(sktCli, (const char *)&logout, sizeof(logout), 0);
            LogoutResult result;
            recv(sktCli, (char *)&result, sizeof(result), 0);
            printf("[server] cmd=%d dataLength=%d iResult=%d\n", result.cmd, result.dataLength, result.iResult);
        }
        else {
        }
    }

    destroy(sktCli);
    return 0;
}

server

//交互命令
enum CMD{
    CMD_LOGIN,
    CMD_LOGIN_RESULT,
    CMD_LOGOUT,
    CMD_LOGOUT_RESULT,
    CMD_ERROR
};
//消息头
struct DataHeader {
    int cmd;//消息指令
    int dataLength;//消息长度
};
//登录消息
struct Login : public DataHeader{
    Login() {
        cmd = CMD_LOGIN;
        dataLength = sizeof(Login);
    }
    char szName[64];//用户名
    char szPass[64];//密码
};
//登录返回消息
struct LoginResult : public DataHeader {
    LoginResult() {
        cmd = CMD_LOGIN_RESULT;
        dataLength = sizeof(LoginResult);
        iResult = 1;
    }
    int iResult;
};
//登出消息
struct Logout : public DataHeader {
    Logout() {
        cmd = CMD_LOGOUT;
        dataLength = sizeof(Logout);
    }
    char szName[64];
};
//登出返回消息
struct LogoutResult : public DataHeader {
    LogoutResult() {
        cmd = CMD_LOGOUT_RESULT;
        dataLength = sizeof(LogoutResult);
        iResult = 2;
    }
    int iResult;
};
//服务端完善结构化消息
int function08() {
    SOCKET sktServ = init("0.0.0.0", 8080);
    if (sktServ == INVALID_SOCKET) {
        return -1;
    }

    SOCKET sktCli = accept(sktServ, NULL, NULL);
    while (true) {
        DataHeader header;
        int ret = recv(sktCli, (char *)&header, sizeof(header), 0);
        if (ret == SOCKET_ERROR) {
            printf("[server] recv error ...\n");
            break;
        }
        if (ret == 0) {
            printf("[client] exit ...\n");
            break;
        }
        printf("[client] cmd=%d datalength=%d\n", header.cmd, header.dataLength);

        switch (header.cmd) {
        case CMD_LOGIN: {
            Login login;
            //客户端发送login结构体,但是服务端前面接受了DataHeader,所以这里只需要接受剩下的消息
            recv(sktCli, (char *)&login + sizeof(DataHeader), sizeof(login) - sizeof(DataHeader), 0);
            printf("[client] name=%s pass=%s\n", login.szName, login.szPass);

            LoginResult result;
            send(sktCli, (const char *)&result, sizeof(result), 0);
            break;
        }
        case CMD_LOGOUT: {
            Logout logout;
            //客户端发送login结构体,但是服务端前面接受了DataHeader,所以这里只需要接受剩下的消息
            recv(sktCli, (char *)&logout + sizeof(DataHeader), sizeof(logout) - sizeof(DataHeader), 0);
            printf("[client] name=%s\n", logout.szName);

            LogoutResult result;
            send(sktCli, (const char *)&result, sizeof(result), 0);
            break;
        }
        default:
            break;
        }
    }

    destroy(sktServ);
    return 0;
}

原文地址:https://www.cnblogs.com/xuqiulin/p/11437696.html

时间: 2024-10-28 10:07:30

windows socket 完善数据简单结构化的相关文章

windows socket 数据简单结构化

client struct DataPackage { int age; char name[32]; }; //结构化的网络消息 int function07() { SOCKET sktCli = init("192.168.3.18", 8080); if (sktCli == INVALID_SOCKET) { return -1; } while (true) { printMenu(); char szCmd[64] = { 0 }; scanf("%s"

【windows socket+UDPserverclient】

Windows Socket+UDPserverclient Winsock是 Windows下套接字标准.                    1.UDP socket编程:          UDP(用户数据报协议)是一个无连接.不可靠的传输数据,其特点是简单,快捷.相比与TCP,UDP不须要建立连接(不需connect.accept函数),数据发送接收之后,不须要终止连接.基于UDP的程序,避免了TCP执行的开销,在效率与速度上具有更好的表现.          UDP是无连接的,可能会

Windows Socket五种I/O模型——代码全攻略(转)

Winsock 的I/O操作: 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序.套接字 默认为阻塞模式.可以通过多线程技术进行处理. 非阻塞模式:执行I/O操作时,Winsock函数会返回并交出控制权.这种模式使用 起来比较复杂,因为函数在没有运行完成就进行返回,会不断地返回 WSAEWOULDBLOCK错误.但功能强大.为了解决这个问题,提出了进行I/O操作的一些I/O模型,下面介绍最常见的三种: Windows Socket五种I/O模型——代码全攻

Windows Socket编程示例-TCP示例程序

前面一部分是介绍,后面有示例 1.网络中进程之间如何通信? 首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的.其实TCP/IP协议族已经帮我们解决了这个问题,网络层的"ip地址"可以唯一标识网络中的主机,而传输层的"协议+端口"可以唯一标识主机中的应用程序(进程).这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互. 使用TCP

c++下基于windows socket的单线程服务器客户端程序

今天自己用编写了一个简单的c++服务器客户端程序,注释较详细,在此做个笔记. windows下socket编程的主要流程可概括如下:初始化ws2_32.dll动态库-->创建套接字-->绑定地址信息-->服务器进行监听/客户端连接服务器-->数据交换-->关闭套接字对象. 服务器端: 1 #include <Winsock2.h> 2 #include <Ws2tcpip.h> 3 #include <iostream> 4 5 #prag

大讲台谈如何运用大数据完善数据中心平台

随着大数据的各个领域的深入应用,大数据的价值正逐渐凸显,而大数据的核心价值在于从海量的复杂数据中挖掘出有价值的信息,通过大数据技术进行更快地分析.更准确地预测,发掘出新的业务模式,创造新的商业发展机会. 因此,大数据时代下,企业迫切需要思考如何应用大数据技术改造完善已有数据中心平台,提升企业的数据处理能力,提高数据分析水平,将大数据融入企业的整体数据方案.CDA数据分析师覆盖了国内企业招聘数据分析师所要求的所有技能,包括统计知识.软件应用(SPSS/SAS/R等).数据挖掘.数据库.报告撰写.项

【windows socket+HTTP服务器客户端】

Windows Socket+HTTP服务器客户端 Winsock是 Windows下套接字标准.                 1.HTTP协议:          HTTP是基于客户端/服务器的请求,响应协议.        请求:由客户端向服务器发起,指定了要从服务器获取的资源.请求包含了协议首部,指明了客户端处理能力信息,如可以处理的文件类型,支持的语言,编码方式等.        响应:服务器收到客户端的请求后,解析这个请求,构造响应,并发送给客户端.响应同样包含了协议首部,指明了服

【windows socket+UDP服务器客户端】

Windows Socket+UDP服务器客户端 Winsock是 Windows下套接字标准.                    1.UDP socket编程:          UDP(用户数据报协议)是一个无连接,不可靠的数据传输,其特点是简单,快捷.相比与TCP,UDP不需要建立连接(不需connect.accept函数),数据发送接收之后,不需要终止连接.基于UDP的程序,避免了TCP运行的开销,在效率与速度上具有更好的表现.          UDP是无连接的,可能会有数据的丢失

【windows socket编程+服务器客户端】

Windows Socket编程与服务器客户端示例 Winsock是 Windows下套接字标准. Socket套接字基于计算机网络,提供同一系统上不同进程或由局域网连接在一起的不同机器上的进程间通讯功能.如下图: 套接字通过IP地址,Port端口号标识,通过这个标识可以在整个局域网定位一个套接字,通过套接字进程便可以相互传输数据.如:进程A与进程B之间欲通过套接字通信,首先进程A创建一个有IP地址,端口号唯一标识的套接字,进程B同样创建一个有IP地址,端口号唯一标识的套接字,进程A,B便可以通