计算机网络(2) --- 网络套接字UDP

计算机网络(1) --- 网络介绍_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/131967378?spm=1001.2014.3001.5501

目录

1.端口号

2.TCP与UDP协议

1.TCP协议介绍

1.TCP协议

2.UDP协议

3.理解

2.网络字节序

发送逻辑

3.socket

1.介绍

2.sockaddr结构

4.UDP协议编程

1.接口介绍

1.创建套接字

2.绑定IP和PORT接口

3.IP介绍

4.网络情况

5.执行接口

5.UPD的服务器和客户端接口实现

1.服务端

1.成员函数

2.接口

3.main函数

4.回调函数

2.客户端

1.成员函数

2.接口

3.main函数


1.端口号

1.IP用于广域网,而MAC地址用于局域网。但是当前解决的问题只是把数据传输到指定的操作系统下,但是这并不意味着成功运行我们想要实现的目的了。我们还想要让程序执行我们想要的。

2.为了解决表示当前操作系统下进程的唯一性,端口号port的引入就是为了保证客户端的唯一性

3.IP+port保证全网的唯一的进程

4.网络通信的本质:进程间通信。公共资源就是网络,通信就是进程的在IO操作

5.pid也可以表示进程的唯一性,但是之所以使用port是为了协议与系统解耦,使得port可以单独设计。

6.操作系统通过映射关系由port找到对应的进程

7.一个端口号只能绑定一个进程,一个进程可以绑定多个端口号

2.TCP与UDP协议

1.TCP协议介绍

1.TCP协议

Transmission Control Protocol 传输控制协议

1.传输层协议
2.有连接:连接两个进程,再传输
3.可靠传输
4.面向字节流

2.UDP协议

User Datagram Protocol 用户数据报协议

1.传输层协议
2.无连接:直接传数据
3.不可靠传输
4.面向数据报

3.理解

特别的:不可靠和可靠其实是一种中性词,它用于不同的场景。可靠是有成本的,写出的协议一定是比较复杂的,并且维护的成本高;不可靠没有成本,比较简单就可以设计和使用了。

2.网络字节序

1.数据在内存中存储,但是不同的主机大小端不同,所以会出现不同主机的大小端不同。那么如果不做任何改变,网络传输时,数据给到另一台大小端不同时,会出现数据的问题。

2.现在的问题是,不知道接收到的数据是大端还是小端,发送也不知道对方认识大端还是小端

3.因此,规定在网络中传输的数据一定是大端。

发送逻辑

1.发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出;
2.接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存;

3.因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址;

4.TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节

5.不管这台主机是大端还是小端, 都会按照这个TCP/IP规定的网络字节序来发送/接收数据;
6.如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略, 直接发送即可

7.系统有专门的接口对数据进行大小端转换:

主机转网络htonl,htons;

网络转主机ntohl,ntohs;

3.socket

1.介绍

1.socket为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。

2.套接字的种类有很多:网络套接字(本地通信使用和主机间使用),原始套接字(绕开上层,直接与物理层等下层协议直接访问),域间套接字(本地通信使用的)

3.设计套接字的一套接口,通过不同参数得到不同的套接字模式解决不同的场景问题

2.sockaddr结构

1.struct sockaddr为最初的结构,它是调用接口的模板结构

2.struct sockaddr_in和struct sockaddr_un为不同格式的套接字

3.struct sockaddr_in和struct sockaddr_un的前位反映了他们对应的结构。那么当我们使用struct sockaddr,只需要读取前16位就知道我们使用的结构体是哪一个了

4.UDP协议编程

1.接口介绍

1.创建套接字

 domain:选择本地通信还是网络通信(AF_INET)

type:选择什么类型的服务提供给网络通信

protocol:未来选择什么协议

调用成功,传出一个fd文件描述符,指向打开的文件

2.绑定IP和PORT接口

addr:填充协议的数据结构,是具体的协议,加入IP和PORT

addrlen:结构体长度

1.server服务器的struct sockaddr_in的sin_addr.s_addr定义为INADDR_ANY:绑定任意IP

2.client客户端不需要绑定,操作系统自动帮忙绑定。当要进行通信时,操作系统检查到套接字没有绑定,随机形成端口号进行绑定

3.之所以server服务器需要手动绑定是因为port需要指定,不能随意的改变;而client客户端不需要考虑port是多少,只需要port唯一即可。

4.在云服务器中,0~1024的端口号不允许使用。

3.IP介绍

1.127.0.0.1:本地环回,用于本地测试的IP;其作用原理是,数据往下传到网络层就回到应用层,不进入物理层。

2.云服务器的IP是虚拟化的服务器,不能作为公网的IP地址

3.ifconfig可以查询内网IP地址,表示的是局域网的IP

4.实际上,一款网络服务器不建议只绑定一个IP,因为真实情况会通过不同的IP来进行访问;使用绑定任意IP,只要端口对应,无论哪个IP传过来都可以执行服务器

4.网络情况

netstat:查看当前网络情况(sudo查询更详细的情况)

-u:udp, -a:all,-p:进程,-n:描述

5.执行接口

buf:特定的缓冲区

flags:读取的模式

scr_addr:谁发送的消息

发送消息

buf:特定的缓冲区

flags:读取的模式

scr_addr:谁发送的消息

5.UPD的服务器和客户端接口实现

1.服务端

namespace Server
{
    enum
    {
        USAGE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        OPEN_ERR
    };

    static const std::string defaultIp = "0.0.0.0";
    static const int gnum = 1024;

    typedef std::function<void(int,std::string, uint16_t, std::string)> func_t;

    class udpServer
    {
    public:
        udpServer(const func_t &cb, const uint16_t port, const std::string ip = defaultIp)
            : _callback(cb), _port(port), _ip(ip), _sockfd(-1)
        {
        }

        void initServer()
        {
            // 1.创建套接字
            _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
            if (_sockfd == -1)
            {
                std::cerr << "socket error: " << errno << " : " << strerror(errno) << std::endl;
                exit(SOCKET_ERR);
            }
            // 告诉操作系统,当前的IP和PORT是多少,上面的代码只是把数据存在堆栈上
            // 2.绑定IP接口
            struct sockaddr_in local;
            bzero(&local, sizeof local); // 清空结构体
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            // local.sin_addr.s_addr = INADDR_ANY;

            int n = bind(_sockfd, (struct sockaddr *)&local, sizeof local);
            if (n == -1)
            {
                std::cerr << "bind error: " << errno << " : " << strerror(errno) << std::endl;
                exit(BIND_ERR);
            }
        }

        void start()
        {
            // 服务器的本质其实就是死循环
            char buffer[gnum];
            for (;;)
            {
                struct sockaddr_in peer;
                socklen_t len = sizeof peer;
                ssize_t s = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, (socklen_t *)&len);
                // 1.数据是什么2.谁发的
                if (s > 0)
                {
                    std::string clientip = inet_ntoa(peer.sin_addr);
                    uint16_t clientport = ntohs(peer.sin_port);
                    std::string massage = buffer;

                    std::cout << clientip << "[" << clientport << "]# " << massage << std::endl;
                    _callback(_sockfd, clientip, clientport, massage);
                }
            }
        }

        ~udpServer()
        {
        }

    private:
        uint16_t _port;
        std::string _ip; // 实际上,一款网络服务器不建议只绑定一个IP
        int _sockfd;
        func_t _callback;
    };
}

1.成员函数

1.uint16_t _port:服务器指定的端口号
2.std::string _ip:客户端发送给服务器的IP,一般建议设置为0,表示任意IP路径过来的都可以访问
3.int _sockfd:需要生成的服务器端网络套接字
4.func_t _callback:回调函数,用于服务器业务处理的

2.接口

1.initServer()创建套接字,先初始化套接字,生成对应的套接字,随后将当前的IP和port绑定(bind)起来

2.start()死循环的执行服务器的任务,把需要发送给客户端发送的语句接收到,随后把客户端的IP和port记录,最后执行回调函数

3.main函数

// ./udpServer port
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);

    signal(2, reload);

    std::unique_ptr<udpServer> usvt(new udpServer(Message, port));

    usvt->initServer();
    usvt->start();
    return 0;
}

main函数先选定需要执行的回调函数,随后创建套接字,运行服务器即可

popen=pipe+fork+exec --- 先打开管道pipe,做重定向与文件指针关联,文件内部fork进程,执行exec

4.回调函数

// demo1
const std::string dictTxt = "./dict.txt";
unordered_map<string, string> dict;

static bool cutString(const string &target, string *s1, string *s2, const string &sep)
{
    auto pos = target.find(sep);
    if (pos == string::npos)
        return false;
    *s1 = target.substr(0, pos);           //[)
    *s2 = target.substr(pos + sep.size()); //[)
    return true;
}

static void debugPrint()
{
    for (auto &e : dict)
    {
        cout << e.first << " " << e.second << endl;
    }
}

void reload()
{
    (void)signo;
    initDict();
}

static void initDict()
{
    ifstream in(dictTxt, std::ios::binary);
    if (!in.is_open())
    {
        cerr << "open file " << dictTxt << " error" << endl;
        exit(OPEN_ERR);
    }

    string line;
    string key, value;
    while (getline(in, line))
    {
        // cout << line << endl;
        if (cutString(line, &key, &value, ":"))
        {
            dict.insert({key, value});
        }
    }

    in.close();
    cout << "load dict success!" << endl;
}

void handlerMessage(int sockfd, std::string clientip, uint16_t clientport, std::string message)
{
    // 处理业务
    string response_message;
    auto iter = dict.find(message);
    if (iter == dict.end())
        response_message = "unkonw";
    else
        response_message = iter->second;

    struct sockaddr_in client;
    bzero(&client, sizeof client);

    client.sin_family = AF_INET;
    client.sin_port = htons(clientport);
    client.sin_addr.s_addr = inet_addr(clientip.c_str());
    sendto(sockfd, response_message.c_str(), response_message.size(), 0, (struct sockaddr *)&client, sizeof client);
}

// demo2
void execMessage(int sockfd, std::string clientip, uint16_t clientport, std::string cmd)
{
    string response;
    FILE *fp = popen(cmd.c_str(), "r");
    if (fp == NULL)
    {
        response = cmd + " exec failed";
    }
    char line[1024];
    while (fget(line, sizeof line, fp))
    {
        response += line;
    }
    pclose(fp);

    struct sockaddr_in client;
    bzero(&client, sizeof client);

    client.sin_family = AF_INET;
    client.sin_port = htons(clientport);
    client.sin_addr.s_addr = inet_addr(clientip.c_str());
    sendto(sockfd, response_message.c_str(), response_message.size(), 0, (struct sockaddr *)&client, sizeof client);
}

// demo3
class User
{
public:
    User(const string &ip, const uint16_t &port) : _ip(ip), _port(port)
    {
    }
    ~User()
    {
    }
    string ip(){ return _ip; }
    uint16_t port(){ return _port; }
private:
    string _ip;
    uint16_t _port;
};

class OnlineUser
{
public:
    OnlineUser() {}
    ~OnlineUser() {}
    void addUser(const string &ip, const uint16_t &port)
    {
        string id = ip + "-" + to_string(port);
        users.insert(make_pair(id, User(ip, port)));
    }
    void delUser(const string &ip, const uint16_t &port)
    {
        string id = ip + "-" + to_string(port);
        users.erase(id);
    }
    bool isOnline(const string &ip, const uint16_t &port)
    {
        string id = ip + "-" + to_string(port);
        return users.find(id) == users.end() ? false : true;
    }
    void broadcastMessage(int sockfd, const string &ip, const uint16_t &port, const string &message)
    {
        for (auto &user : users)
        {
            struct sockaddr_in client;
            bzero(&client, sizeof(client));

            client.sin_family = AF_INET;
            client.sin_port = htons(user.second.port());
            client.sin_addr.s_addr = inet_addr(user.second.ip().c_str());
            string s = ip + "-" + to_string(port) + "# ";
            s += message;
            sendto(sockfd, s.c_str(), s.size(), 0, (struct sockaddr *)&client, sizeof(client));
        }
    }

private:
    unordered_map<string, User> users;
};

void routeMessage(int sockfd, string clientip, uint16_t clientport, string message)
{
    if (message == "online")
        onlineuser.addUser(clientip, clientport);
    if (message == "offline")
        onlineuser.delUser(clientip, clientport);
    if (onlineuser.isOnline(clientip, clientport))
    {
        // 消息的路由
        onlineuser.broadcastMessage(sockfd, clientip, clientport, message);
    }
    else
    {
        struct sockaddr_in client;
        bzero(&client, sizeof(client));

        client.sin_family = AF_INET;
        client.sin_port = htons(clientport);
        client.sin_addr.s_addr = inet_addr(clientip.c_str());

        string response = "你还没有上线,请先上线,运行: online";

        sendto(sockfd, response.c_str(), response.size(), 0, (struct sockaddr *)&client, sizeof(client));
    }
}

demo的逻辑都是先接收到客户端的信息,通过回调函数执行对应的任务,最后把结果发送给客户端。

此外,将服务端的类和回调函数分离,这样使得耦合度变低,只在main函数修改每一次的指令即可更换命任务。

2.客户端

namespace Client
{
    class udpClient
    {
    public:
        udpClient(const std::string serverip, const uint16_t serverport)
            : _sockfd(-1), _serverport(serverport), _serverip(serverip), _quit(false)
        {
        }

        void initClient()
        {
            // 1.创建套接字
            _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
            if (_sockfd == -1)
            {
                std::cerr << "socket error: " << errno << " : " << strerror(errno) << std::endl;
                exit(2);
            }
            std::cout << "socket success: " << _sockfd << std::endl;
            // 2.绑定IP接口,Client不需要程序员显示的bind,由操作系统进行绑定
        }

        void run()
        {
            struct sockaddr_in server;
            memset(&server, 0, sizeof server);
            server.sin_family = AF_INET;
            server.sin_addr.s_addr = inet_addr(_serverip.c_str());
            server.sin_port = htons(_serverport);

            std::string massage;
            while (!_quit)
            {
                std::cout << "Please Enter# ";
                std::cin >> massage;

                sendto(_sockfd, massage.c_str(), massage.size(), 0, (struct sockaddr *)&server, sizeof server);

                char buffer[1024];
                struct sockaddr_in temp;
                socklen_t temp_len = sizeof temp;
                ssize_t n = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&temp, &temp_len);
                if (n > 0)
                    buffer[n] = 0;
                std::cout << "服务器的翻译结果:" << buffer << std::endl;
            }
        }

        //demo3的设计
        // static void *readMessage(void *args)
        // {
        //     int sockfd = *(static_cast<int *>(args));
        //     pthread_detach(pthread_self());
        //     while (true)
        //     {
        //         char buffer[1024];
        //         struct sockaddr_in temp;
        //         socklen_t temp_len = sizeof(temp);
        //         size_t n = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&temp, &temp_len);
        //         if (n >= 0)
        //             buffer[n] = 0;
        //         cout << buffer << endl;
        //     }

        //     return nullptr;
        // }

        // void run()
        // {
        //     pthread_create(&_reader, nullptr, readMessage, (void *)&_sockfd);

        //     struct sockaddr_in server;
        //     memset(&server, 0, sizeof(server));
        //     server.sin_family = AF_INET;
        //     server.sin_addr.s_addr = inet_addr(_serverip.c_str());
        //     server.sin_port = htons(_serverport);

        //     string message;
        //     char cmdline[1024];
        //     while (!_quit)
        //     {
        //         // cerr << "# "; // ls -a -l
        //         //  cin >> message;
        //         fprintf(stderr, "Enter# ");
        //         fflush(stderr);
        //         fgets(cmdline, sizeof(cmdline), stdin);
        //         cmdline[strlen(cmdline) - 1] = 0; // 回车置为/0
        //         message = cmdline;
        //         sendto(_sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&server, sizeof(server));
        //     }
        // }

        ~udpClient()
        {
        }

    private:
        int _sockfd;
        std::string _serverip;
        uint16_t _serverport;
        bool _quit;
    };
}

1.成员函数

int _sockfd:客户端的套接字

std::string _serverip:服务器的IP地址

uint16_t _serverport:服务器的端口号

bool _quit:执行条件逻辑判断变量

2.接口

1.initClient()初始化客户端的套接字,再绑定套接字

2.run(),客户端先准备好数据,发送给服务端,随着服务端的任务处理,把最终服务端的套接字发送给运行的客户端,得到自己的需求

3.main函数

static void Usage(string proc)
{
    cout << "Usage:\n\t" << proc << " server_ip server_port\n\n";
}

// ./udpClient server_ip server_port
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(1);
    }
    uint16_t serverport = atoi(argv[2]);
    std::string serverip = argv[1];
    std::unique_ptr<udpClient> ucli(new udpClient(serverip, serverport));
    ucli->initClient();
    ucli->run();
    return 0;
}

main函数初始化套接字,随后运行即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/58967.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

小白到运维工程师自学之路 第六十六集 (docker 网络模型)

一、概述 Docker网络模型是指Docker容器在网络中的通信方式和组织结构。Docker容器通过网络连接&#xff0c;使得容器之间可以相互通信&#xff0c;并与主机和外部网络进行交互。 在Docker中&#xff0c;有几种不同的网络模型可供选择&#xff1a; 1、主机模式&#xff08;H…

网络安全(黑客)自学建议一一附学习路线

温馨提示&#xff1a;为了避免误入歧途&#xff0c;自学请优先看《网络安全法》。 下面是一些学习建议&#xff1a; 1、多请教有经验的人 切忌钻牛角尖&#xff0c;特别是刚入门的什么都不了解的情况下&#xff0c;可能你花好几天研究的一个东西&#xff0c;人10分钟就能搞定…

DBeaver连MySQL库报错public key retrieval is not allowed

连接报错: public key retrieval is not allowed解决办法&#xff1a; 右击你连接的库进行编辑连接&#xff08;或者直接按F4打开编辑&#xff09; 然后点击驱动属性里面进行设置 找到allowPublicKeyRetrieval属性&#xff0c;把值由false改为true 注&#xff1a;连接成功后如…

部署SpringBoot项目在服务器上,并通过swagger登录

1.项目编译打包 2.上传jar包到服务器并启动 xftp将打包好后的jar包传到虚拟机指定路径 java -jar执行该jar包 3.通过swagger登录 输入后点击下面的执行按钮 会得到一个tocken 4.将tocken放到postman的Headers中 5.修改url 例如我本地测试是http://localhost:8080/接口名&am…

【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域)

文章目录 一、继承的定义1.定义格式2.继承基类成员访问方式的变化 二、基类和派生类对象赋值转换三、继承的作用域1. 在继承体系中基类和派生类都有独立的作用域。2.子类和父类中有同名成员3.成员函数的隐藏4.注意在实际中在继承体系里面最好不要定义同名的成员。 四、派生类的…

【WebRTC---序篇】(七)RTC多人连麦方案

服务端可以选择mediasoup&#xff0c;作为SFU服务器&#xff0c;只负责转发数据 下图举例三个Client (browser或者客户端)同时加入一个房间&#xff0c;每个app同时发布一路视频和一路音频&#xff0c;并且接受来自其他app的音视频流&#xff0c;mediasoup内部的结构如下&…

【诺依管理系统-前端】对话框

1.指定 v-model"openAllScene" 2.按钮代码 3.调用方法handleAddAllScene里面&#xff0c;只是openAllScene的值为true&#xff0c;调用显示对话框

unity tolua热更新框架教程(1)

git GitHub - topameng/tolua: The fastest unity lua binding solution 拉取到本地 使用unity打开&#xff0c;此处使用环境 打开前几个弹窗(管线和api升级)都点确定 修改项目设置 切换到安卓平台尝试打包编译 设置包名 查看报错 打开 屏蔽接口导出 重新生成 编译通过 …

Git常见问题

git clone 提示OpenSSL SSL_read git clone 时提示Connection was reset, errno 10054类错误 fatal: unable to acce ss https://github.com/fex-team/ueditor.git/: OpenSSL SSL_read: Connection was reset, errno 10054 备注&#xff1a;以下方法只是归纳整理&#xff0c;…

JVM GC ROOT分析

GC root原理:通过对枚举GCroot对象做引用可达性分析,即从GC root对象开始,向下搜索,形成的路径称之为 引用链。如果一个对象到GC roots对象没有任何引用,没有形成引用链,那么该对象等待GC回收,换而言之,如果减少内存泄漏,也就是切断引用链,常见的GCRoot对象如下: 1、…

【深度学习】在 MNIST实现自动编码器实践教程

一、说明 自动编码器是一种无监督学习的神经网络模型&#xff0c;主要用于降维或特征提取。常见的自动编码器包括基本的单层自动编码器、深度自动编码器、卷积自动编码器和变分自动编码器等。 其中&#xff0c;基本的单层自动编码器由一个编码器和一个解码器组成&#xff0c;编…

简单易懂的生鲜蔬果小程序开发指南

随着人们对健康意识的提高&#xff0c;越来越多的人开始注重饮食健康&#xff0c;选择新鲜的果蔬产品。为了满足市场需求&#xff0c;制作一个果蔬配送小程序成为了一个不错的选择。本文将详细介绍如何快速制作一个果蔬配送小程序。 第一步&#xff1a;登录乔拓云网后台&#x…

<van-empty description=““ /> 滚动条bug

使用 <van-empty description"" /> 时&#xff0c;图片出现了个滚动条&#xff0c;图片可以上下滑动。 代码如下&#xff1a; <block wx:if"{{courseList.length < 0}}"><van-empty description"" /> </block> <…

VLAN原理+配置

目录 一&#xff0c; 以太网二层交换机 二&#xff0c;三层架构&#xff1a; 三&#xff0c;VLAN配置思路 1.创建vlan 2.接口划入vlan 3.trunk干道 4.vlan间路由器 5.DHCP池塘配置 四&#xff0c;华为VLAN部分的接口模式讲解&#xff1a; 五&#xff0c;华为VLAN部分的…

mysql报错:name ‘_mysql‘ is not defined

原因是&#xff1a; Mysqldb 不兼容 python3.5 以后的版本 解决办法&#xff1a; 使用pymysql代替MySQLdb 在项目应用下的__init__.py 添加上去 import pymysqlpymysql.version_info (1, 4, 13, "final", 0) pymysql.install_as_MySQLdb()

【ChatGLM_02】LangChain知识库+Lora微调chatglm2-6b模型+提示词Prompt的使用原则

经验沉淀 1 知识库1.1 Langchain知识库的主要功能(1) 配置知识库(2) 文档数据测试(3) 知识库测试模式(4) 模型配置 2 微调2.1 微调模型的概念2.2 微调模型的方法和步骤(1) 基于ptuning v2 的微调(2) 基于lora的微调 3 提示词3.1 Prompts的定义及原则(1) Prompts是什么&#xf…

计算机网络(4) --- 协议定制

计算机网络&#xff08;3&#xff09; --- 网络套接字TCP_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/132035757?spm1001.2014.3001.5501 目录 1. 协议的基础知识 TCP协议通讯流程 ​编辑 2.协议 1.介绍 2.手写协议 1.内容 2.接口 …

Vue3 watch监听器

概览&#xff1a;watch监听器的定义以及使用场景。在vue3中的监听器的使用方式&#xff0c;watch的三个参数&#xff0c;以及进一步了解第一个参数可以是一个属性&#xff0c;也可以是一个数组的形式包含多个属性。 watch在vue3和vue2中的使用&#xff1a; vue3中&#xff1a…

填补5G物联一张网,美格智能快速推进RedCap商用落地

自5G R17版本标准冻结以来&#xff0c;RedCap一直引人注目。2023年更是5G RedCap突破性发展的一年&#xff0c;从首款5G RedCap调制解调器及射频系统——骁龙X35发布&#xff0c;到国内四大运营商发布RedCap技术白皮书&#xff0c;芯片厂商、模组厂商、运营商及终端企业都在积极…

不懂这些专业名词,你很难成为有水平的项目经理——数据分析篇

大家好&#xff0c;我是老原。 前段时间我们项目组招了个新人小林&#xff0c;让他去和产品经理对下产品上线情况&#xff0c;等到下班也没等来反馈。 第二天在茶水间遇到了产品经理就问了一嘴&#xff0c;才知道已经对接到位了。 一问小林才知道&#xff0c;他完全不知道产…