46 udp网络程序

news2024/12/23 8:58:27

查询网络服务的命令

netstat -nlup
n: 显示数字
a:显示所有
u:udp服务
p:显示pid

在这里插入图片描述
Recv-Q收到的数量,本地ip和远端ip,00表示可以收到任何地址

网络聊天

服务端

定义一个server类,成员保存ip地址,端口号,文件描述符,是否运行
在这里插入图片描述
ip和端口号构造时设置默认值,“0.0.0.0”和“8000”
在这里插入图片描述

  • init函数内初始化套接字,返回文件描述符,然后绑定到os。
    在这里插入图片描述
    socket的三个参数,协议族IPv4,套接字类型面向字节流,协议0自动选择,面向字节流默认匹配udp
    返回值描述符,是后续功能传入的第一个参数

  • bind函数建立本地捆绑
    在这里插入图片描述
    第二个参数需要sockaddr类型,这个通用类型需要用sockaddr_in类型强转
    在这里插入图片描述

设置sockaddr_in的结构内容:
初始化为0
设置协议族
ip地址,需要将点分十进制转换为32位整数类型uint32_t,然后转为网络字节序
端口转为网络字节序

ip地址转化方法
在这里插入图片描述
先定义ip结构体,每个成员8位,总共4字节
字符串转整数:
1.先去掉.符号,切割为四个整数
2.然后定义一个uint32变量,强转为ip结构体
3.每个部分对应分割的字符串,将字符串转整数

整数转字符串:
1.强制转换为ip结构
2.将每部分转为字符串加上.拼接为点分

  • run函数内接收和发送消息

在这里插入图片描述在这里插入图片描述

rev第一个参数标识符,第二个接收存放的缓冲区,缓冲区大小,调用方式,0表示阻塞直到有数据或错误,对方的协议结构,协议结构的长度(socklen_t类型)
send参数,标识符,发送内容,内容的大小,调用方式0,不使用特殊行为,对方的协议结构,协议的长度

启动服务端查看有没有服务
在这里插入图片描述

ip和port说明
ip可以固定设置,如果是本机ip,虚拟机是可以的,云服务器禁止绑定公网ip。ip填0的意思是,凡是发给我主机的数据,都根据端口号向上交付,如果有两张网卡,固定设置,只会收到发往一个的,0可以收到任一个网卡的,可以提前设置ip,也可以在绑定时设置

addrin.sin_addr.s_addr = INADDR_ANY;

【0,1023】是系统内定的端口号,有固定的应用层协议使用,http:80 https:443 mysql:3306。。也有几个这种特殊的,所以设置端口号时尽量往大一点设置

#pragma once
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "log.hpp"

enum
{
    SOCK_ERR = 1
};

uint16_t defaultport = 8000;
std::string defaultip = "0.0.0.0";

Log log;
class server
{ 
public:
    server(const std::string ip = defaultip, const uint16_t port = defaultport)
    {
        _ip = ip;
        _port = port;
        _sockfd = 0;
    }

    void init()
    {
        //1.创建套接字
        int _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd < 0)
        {
            log.logmessage(fatal, "socket create error:%d", _sockfd);
            exit(SOCK_ERR);
        }

        log.logmessage(info, "socket create success:%d", _sockfd);

        //绑定
        sockaddr_in addrin;
        bzero(&addrin, sizeof(addrin));
        addrin.sin_family = AF_INET;
        addrin.sin_addr.s_addr = htonl(inet_addr(_ip.c_str()));
        addrin.sin_port = htons(_port);
        addrin.sin_addr.s_addr = INADDR_ANY;

        int ret = bind(_sockfd, (const sockaddr*)&addrin, sizeof(addrin));
        if (ret < 0)
        {
            log.logmessage(fatal, "bind error:%s", strerror(errno));
        }
        log.logmessage(info, "bind success:%d", ret);

    }

    void run()
    {
        _isrunning = true;
        char buff[1024];
        while (_isrunning)
        {
            sockaddr client;
            socklen_t len = sizeof(client);
            ssize_t n = recvfrom(_sockfd, buff, sizeof(buff) - 1, 0, &client, &len);
            if (n < 0)
            {
                //log.logmessage(warning, "recv error:%s", strerror(errno));
            }

            buff[1024] = 0;
            std::string echo_string = buff;
            echo_string = "client#" + echo_string;
            sendto(_sockfd, echo_string.c_str(), echo_string.size(), 0, &client, len);
        }
    }
 
    ~server()
    {
        if (_sockfd > 0)
            close(_sockfd);
    }

private:
    int _sockfd;      // 网路文件描述符
    uint16_t _port;   // 任意地址bind 0
    std::string _ip;  // 表明服务器进程的端口号
    bool _isrunning;
};

客户端

先初始化端口和ip,这个安装软件使用的时候已经默认设好了。这里定为服务器的ip和刚刚启动服务的端口

设置目标协议addr结构,内容为上面初始化
在这里插入图片描述

打开套接字
在这里插入图片描述

客户端也是需要绑定的,只不过不是用户显示绑定,由os随机选择,一个端口号只能被一个进程绑定,对服务端也是如此。客户端的port只需要保证主机上的唯一性,在首次发送数据的时候会自动绑定

和服务端一样,发送和接受消息,只不过客户端先发送再接收
在这里插入图片描述

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <strings.h>

using namespace std;
int main()
{

    uint16_t port = 8000;
    string ip = "ip";
    sockaddr_in in;
    bzero(&in, sizeof(in));
    in.sin_family = AF_INET;
    in.sin_addr.s_addr = inet_addr(ip.c_str());
    in.sin_port = htons(port);
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        cout << "socket error" << endl;
    }

    //client 需要绑定,但不显示绑定,由os自由选择

    string message;
    char buff[1024];
    while (true)
    {
        cout << "please enter: ";
        getline(cin , message);

        sendto(sockfd, message.c_str(), message.size(), 0, (const sockaddr*)&in, sizeof(in));
        sockaddr_in rec;
        socklen_t len = sizeof(rec);
        ssize_t s = recvfrom(sockfd, buff, sizeof(buff) - 1, 0, (sockaddr*)&rec, &len);
        if (s > 0)
        {
            buff[s] = 0;
            cout << buff << endl;
        }
    }

    close(sockfd);
}

注意
hton转字节序的函数是根据本机字节序情况转换,如果本机是小端调用几次会转几次

打开云主机端口
如果程序没问题,但收发不到消息,可以试着打开云主机的防火墙端口,以腾讯云为例:
登录控制台,查看详情,防火墙添加规则
在这里插入图片描述

服务端自定义数据处理
使用自定义函数类型,run调用实例出的函数,实现数据处理方法的自定义

using func_t = std::function<std::string(const std::string &)>; //定义函数类型

std::string handler(const std::string& str)
{
    std::string s = "server get message: ";
    s += str;
    std::cout << s << std::endl;
    return s;
}

命令bash

服务端可以收到信息了,也可以将收到的内容当做其他形式。如果将收到的内容当做xshell命令,就会执行命令
run执行的函数替换。popen函数可以创建子进程通信管道,将传入的命令创建子进程执行。将命令执行的结果添加到字符串内,回显发送给客户端

std::string execute(const std::string& cmd)
{
    //safecheck 不想执行的命令安全检查
    FILE* fp = popen(cmd.c_str(), "r");
    if (fp == nullptr)
    {
        perror("popen");
        return "error";
    }

    string ret;
    char buff[4096];
    while (true)
    {
        char *ok = fgets(buff, sizeof(buff), fp);
        if (ok == nullptr)
        {
            break;
        }

        ret += buff;
    }

    pclose(fp);
    return ret;
}

在这里插入图片描述

本地环回地址

只会在本地协议走一遍,不会发向网络,通常用来测试

xshell

这就是为什么要用xshell登录,就相当于客户端,将命令发到了远端的服务器,接受到字符串执行命令,然后将结果发送回xshell显示

后台里有一个ssh的tcp服务,端口号22号接收发送的命令
在这里插入图片描述

win客户端

实现让win客户端和linux服务端网络通讯
win需要包含头文件WinSock2.h头文件和ws2_32.lib网络库
上面的头文件要在windows.h这个头文件之前,不然会报错

在这里插入图片描述

首先初始化网络版本信息,addr协议内容
在这里插入图片描述
打开套接字
在这里插入图片描述

收发功能和前面一样
在这里插入图片描述
清理数据
在这里插入图片描述
在这里插入图片描述
两边汉字编码不一样,可能会显示有问题

#include <iostream>
#include <string>
#include <WinSock2.h>
//#include <Windows.h>

//关闭安全警告
#pragma warning(disable:4996)
//包含网络库
#pragma comment(lib, "ws2_32.lib")

using namespace std;
string ip = "ip";
uint16_t port = 8000;

int main()
{
	//初始化socket数据
	WSADATA wsd;
	WSAStartup(MAKEWORD(2, 2), &wsd);

	sockaddr_in server;
	memset(&server, 0, sizeof(server));
	server.sin_family = AF_INET;
	server.sin_addr.S_un.S_addr = inet_addr(ip.c_str());
	server.sin_port = htons(port);

	//套接字
	SOCKET sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sockfd == SOCKET_ERROR)
	{
		cout << "sock error" << endl;
		return 1;
	}

	string message;
	char buff[1024];
	while (true)
	{
		cout << "please enter: ";
		getline(cin, message);

		sendto(sockfd, message.c_str(), message.size(), 0, (const sockaddr*) & server, sizeof(server));
		sockaddr_in temp;
		int len = sizeof(temp);
		int s = recvfrom(sockfd, buff, 1023, 0, (sockaddr*)&temp, &len);
		if (s > 0)
		{
			buff[s] = 0;
			cout << buff << endl;
		}
	}

	closesocket(sockfd);
	WSACleanup();
	return 0;
}


网络聊天室 (多线程)

聊天室功能需要用户名标识每一个主机,这里用对方的ip和port作为区分,发言的前缀
用一个无序map容器,string作为索引,值存addr结构
在这里插入图片描述

将收到的addr结构转为主机序列加入到显示屏幕的内容

在这里插入图片描述
在这里插入图片描述

检查如果是新的主机就加入到_online结构,并显示新主机加入
在这里插入图片描述
遍历容器内容,将最新消息发送给所有用户
在这里插入图片描述
sendto可以自动转网络序列,所以容器内容不需要转换

上面可以实现接收到不同用户的消息,但有个问题,客户端的getline没有内容时是一直阻塞住的,不输入内容的时候收不到其他消息。所以用多线程,一个线程收消息,一个线程发消息

两个线程都需要文件描述符和addr结构
定义一个结构体,将初始化的内容赋值给结构体在这里插入图片描述

在这里插入图片描述
这时可以显示其他人的消息,但自己因为发送和接收的顺序无法正常接收。需要将输入和输出的终端分开

在这里插入图片描述

/dev/pts 这个文件里保存了所有打开的终端

在这里插入图片描述

0号终端重定向到6,显示到了1号页面中,所以文件6代表了下面这个终端,5是上面的终端。在接收消息后想显示到上面的终端,下面的用来发送,由于线程的文件描述共享,所以将标准错误重定向到5,在下面打开服务端

在这里插入图片描述

上面的内容可以简化,打开两个端口,提前确定哪个用来显示,另一个启动客户端,将标准错误重定向到显示端
在这里插入图片描述

服务端

#pragma once
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <functional>
#include <unordered_map>
#include "log.hpp"

enum
{
    SOCK_ERR = 1
};

uint16_t defaultport = 8000;
std::string defaultip = "0.0.0.0";
using func_t = std::function<std::string(const std::string &)>; //定义函数类型
//typedef std::function<std::string(const std::string &)> func_t

Log log;
class server
{ 
public:
    server(const std::string ip = defaultip, const uint16_t port = defaultport)
    {
        _ip = ip;
        _port = port;
        _sockfd = 0;
    }

    void init()
    {
        //1.创建套接字
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd < 0)
        {
            log.logmessage(fatal, "socket create error:%d", _sockfd);
            exit(SOCK_ERR);
        }

        log.logmessage(info, "socket create success:%d", _sockfd);

        //绑定
        struct sockaddr_in local;
        bzero(&local, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_addr.s_addr = inet_addr(_ip.c_str());
        local.sin_port = htons(_port);
        //local.sin_addr.s_addr = INADDR_ANY;

        int ret = bind(_sockfd, (const sockaddr*)&local, sizeof(local));
        if (ret < 0)
        {
            log.logmessage(fatal, "bind error:%s", strerror(errno));
        }
        log.logmessage(info, "bind success:%d", ret);

    }

    void checkuser(const struct sockaddr_in& sock, const string ip, const uint16_t port)
    {
        auto it = _online.find(ip);
        if (it == _online.end())
        {
            _online.insert({ip, sock});
            cout << "[" << ip << ":" << port << "] add new user" << endl;
        }
    }

    void broadcast(const string& message, string ip, uint16_t port)
    {
        for (const auto user : _online)
        {
            socklen_t len = sizeof(user.second);
            sendto(_sockfd, message.c_str(), message.size(), 0, (struct sockaddr*)(&user.second), len);
        }
    }

    void run(func_t func)
    {
        _isrunning = true;
        char buff[1024];
        while (_isrunning)
        {
            sockaddr_in client;
            socklen_t len = sizeof(client);
            ssize_t n = recvfrom(_sockfd, buff, sizeof(buff) - 1, 0, (sockaddr*)&client, &len);
            if (n < 0)
            {
                //log.logmessage(warning, "recv error:%s", strerror(errno));
                continue;
            }

            buff[n] = 0;
            //获取端口号和ip
            string ip = inet_ntoa(client.sin_addr);
            // 网络字节序转主机
            uint16_t port = ntohs(client.sin_port);

            checkuser(client, ip, port);
            std::string echo_string = "[" + ip + ":" + to_string(port) + "]: " + buff;
            broadcast(echo_string, ip, port);
            // std::cout << echo_string << endl;
            //  echo_string = func(echo_string);
            //sendto(_sockfd, echo_string.c_str(), echo_string.size(), 0, (const sockaddr *)&client, len);
        }
    }
 
    ~server()
    {
        if (_sockfd > 0)
            close(_sockfd);
    }

private:
    int _sockfd;      // 网路文件描述符
    uint16_t _port;   // 任意地址bind 0
    std::string _ip;  // 表明服务器进程的端口号
    bool _isrunning;
    //用ip检索
    unordered_map<string, struct sockaddr_in> _online;  //注册主机
};

客户端

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include <fcntl.h>

using namespace std;

string path = "/dev/pts/5";
struct thread_data
{
    int _sockfd;
    struct sockaddr_in _server;
    string _ip;
};

void *send_message(void * temp)
{
    thread_data *td = (struct thread_data*)temp;
    string message;
    cout << "welcome " << td->_ip << endl;
    while (true)
    {
        cout << "please enter: ";
        getline(cin, message);
        sendto(td->_sockfd, message.c_str(), message.size(), 0, (const sockaddr *)&td->_server, sizeof(td->_server));
    }
    
}

void* recv_message(void* temp)
{
    // int fd = open(path.c_str(), O_WRONLY);
    // if (fd < 0)
    // {
    //     perror("open");
    // }

    // dup2(fd, 2);

    thread_data *td = (struct thread_data *)temp;
    char buff[1024];
    sockaddr_in rec;
    socklen_t len = sizeof(rec);
    while (true)
    {
        ssize_t s = recvfrom(td->_sockfd, buff, sizeof(buff) - 1, 0, (sockaddr *)&rec, &len);
        if (s > 0)
        {
            buff[s] = 0;
            cerr << buff << endl;
        }
    }

    //close(fd);
}

int main()
{
    thread_data td;
    uint16_t port = 8000;
    string ip = "ip";
    sockaddr_in in;
    bzero(&in, sizeof(in));
    td._server.sin_family = AF_INET;
    td._server.sin_addr.s_addr = inet_addr(ip.c_str());
    td._ip = ip;
    td._server.sin_port = htons(port);
    td._sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (td._sockfd < 0)
    {
        cout << "socket error" << endl;
    }

    //client 需要绑定,但不显示绑定,由os自由选择
    pthread_t tid_send;
    pthread_t tid_recv;
    pthread_create(&tid_send, nullptr, send_message, &td);
    pthread_create(&tid_recv, nullptr, recv_message, &td);  
    
    pthread_join(tid_send, nullptr);
    pthread_join(tid_recv, nullptr);

    close(td._sockfd);
}

地址转换函数

介绍基于ipv4的socket网络编程,struct in_addr sin_addr表示32位的ip地址,但是我们通常用点分十进制字符串表示ip地址,一下函数可以在字符串表示和in_addr表示之间转换

其中inet_pton和inet_ntop不仅可以转换ipv4的in_addr,还可以转换ipv6的in6_addr,因此接口是void* addrptr

字符串转in_addr函数:
在这里插入图片描述在这里插入图片描述
in_addr转字符串函数:
在这里插入图片描述在这里插入图片描述

关于inet_ntoa

这个函数返回一个char*,自己内部申请了一块内存保存ip的结果,那么需不需要手动释放呢?

在这里插入图片描述
man手册说返回结果放在了静态存储区,不需要手动释放

当多次调用时,两个不同ip都会转换为相同的结果,以最后一个为准
因为inet_ntoa把结果放到内部的静态缓存区,第二次调用的时候会覆盖上一次结果。APUE中,明确提出inet_ntoa不是线程安全的函数,但是centos7上测试,没有出现问题,可能是内部实现加了互斥锁,在多线程环境下,推荐使用inet_ntop,这个函数由用户提供缓冲区结果,可以规避线程安全的问题

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAVA毕业设计138—基于Java+Springboot+Vue的医院预约挂号小程序(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootVue的医院预约挂号小程序(源代码数据库)138 一、系统介绍 本系统前后端分离带小程序和后台 小程序&#xff08;用户端&#xff09;&#xff0c;后台管理系统&a…

SQLite性能测试(插入)

最近一直在思考一个问题&#xff0c;SQLite 做到这么轻量级&#xff0c;那它注定不会像 MySql 一样强性能&#xff0c;那么它的性能怎么样呢&#xff1f;并发量多高呢&#xff1f; 官方解释&#xff1a; About SQLite 最大数据库大小&#xff1a;281TB 最大行大小&#xff1…

LVDS 接口标准和规范

低压差分信号具有传输速率快、抗干扰性强的特点&#xff0c;是现在广泛应用的数据接口标准之一。Xilinx FPGA支持LVDS电平标准&#xff0c;并提供了动态相位调整解决方案&#xff0c;解决了基于LVDS源同步传输时存在的数据偏斜问题。 1 LVDS 技术规范简介 随着接口和背板信号…

最新巨量X-Bogus、_signature参数逆向分析与算法还原

文章目录 1. 写在前面2. 接口分析3. 断点分析4. 扣代码补环境5. 数据解密 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路…

BGP(border gateway protocol)边界网关协议初识篇

BGP它是一种路径矢量协议&#xff0c;用于决定数据包在互联网中的最佳路径。 1、工作原理&#xff1a; 自治系统&#xff08;AS&#xff09;间路由: BGP主要用于连接不同自治系统之间的路由器&#xff0c;其中每个自治系统&#xff08;AS&#xff09;代表一组具有共同路由的网…

【MySQL】基本操作

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;MySQL 目录 &#x1f449;&#x1f3fb;创建和删除数据库&#x1f449;&#x1f3fb;数据库编码集和数据库校验集校验规则对数据库的影响 &#x1f449;&…

如何在matlab时间序列中X轴标注月-日

一般我们使用的时间序列都是以年为单位&#xff0c;比如下图&#xff1a; 而如果要绘制月尺度的时间变化图&#xff0c;则需要调整X轴的标注。下面代码展示了如何绘制小时尺度的降水数据。 [sname2,lon2,lat2] kml2xy(GZ_.kml); nc_bound2 [lon2,lat2]; area_ind2inpolygon(e…

Remix Client/Server 架构

Remix 框架是服务端渲染架构&#xff0c;当路由请求时生成 HTML 并返回浏览器。这种 SSR 是如何实现的呢&#xff1f;如果不使用 Remix 这种框架&#xff0c;可以在服务器段启动一个无头浏览器进行页面渲染并返回&#xff0c;代价就是要在服务器上启动一个 Chrome 服务&#xf…

AI语音模型PaddleSpeech踩坑(安装)指南

PaddleSpeech简介 PaddleSpeech 是基于飞桨 PaddlePaddle 的语音方向的开源模型库&#xff0c;用于语音和音频中的各种关键任务的开发&#xff0c;包含大量基于深度学习前沿和有影响力的模型。 PaddleSpeech安装步骤 提示&#xff1a;要找到一个合适的PaddleSpeech版本与pad…

乡村旅游指标-最美乡村数、旅游示范县数、旅行社数、景区数、农家乐数(2007-2021年)

01、数据介绍 乡村旅游也是促进乡村经济发展的有效途径。通过发展乡村旅游&#xff0c;可以带动乡村相关产业的发展&#xff0c;提高乡村居民的收入&#xff0c;促进乡村的经济发展和社会进步。此外&#xff0c;乡村旅游还能促进城乡交流&#xff0c;推动城乡统筹发展。 数据…

简易留言板

目录 前端实现 数据库的使用 创建数据表 创建项目 连接数据库 后端实现 接口定义 持久层 业务逻辑层 控制层 前端代码完善 留言板是一个常见的功能&#xff0c;在本篇文章中&#xff0c;将实现一个简易的留言板&#xff1a; 页面中能够显示所有留言内容&#xff0c…

刷代码随想录有感(63):将有序数组转换为二叉搜索树(其实时二叉平衡搜索树)

题干&#xff1a; 代码&#xff1a; class Solution { public:TreeNode* traversal(vector<int>& nums, int left, int right){if(left > right)return NULL;int mid left (right - left)/2;TreeNode* NewRoot new TreeNode(nums[mid]);NewRoot->left tra…

maven mirrorOf的作用

在工作中遇到了一个问题导致依赖下载不了&#xff0c;最后发现是mirror的问题&#xff0c;决定好好去看一下mirror的配置&#xff0c;以及mirrorOf的作用&#xff0c;以前都是直接复制过来使用&#xff0c;看了之后才明白什么意思。 过程 如果你设置了镜像&#xff0c;镜像会匹…

HIVE调优MapJoin

HIVE调优MapJoin 目录 HIVE调优MapJoin 1.mapjoin &#xff08;1.2以后自动默认启动mapjoin&#xff09; 2.创建表格 3.查询建表 4.通过 explain 展示执行计划 5.Map JOIN 相关设置&#xff1a; 1.mapjoin &#xff08;1.2以后自动默认启动mapjoin&#xff09;…

SpringBoot内置插件的使用(jackson和lombok)

文章目录 引言I lombok(自动为属性生成构造器)II jacksonsee also引言 idea2021.2.2 已经捆绑安装jackson和lombok插件 I lombok(自动为属性生成构造器) Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。 https://p…

【SpringBoot】Redis Lua脚本实战指南:简单高效的构建分布式多命令原子操作、分布式锁

文章目录 一.Lua脚本1.Lua特性2.Lua优势 二.Lua语法1.注释2.变量3.数据类型&#xff1a;3.1.基本类型3.2.对象类型&#xff1a;表&#xff08;table&#xff09; 4.控制结构&#xff1a;4.1.条件语句: 使用if、else和elseif来实现条件分支。4.2.循环结构&#xff1a;Lua支持for…

大模型面试常考知识点2

文章目录 1. LLM推理attention优化技术KV CachePageAttention显存优化MHA\GQA\MQA优化技术FlashAttention优化技术稀疏Attention1. Atrous Self Attention2. Local Self Attention3. Sparse Self Attention 2. LLM数据处理关键去重多样性保证构造扩充数据充分利用数据 参考文献…

前端小程序调用 getLocation 实现地图位置功能,通过 纬度:latitude 经度: longitude 获取当前位置

1、首先登录一下 腾讯的位置服务 有账号就登录没账号就注册&#xff0c; 点击右上角的控制台点击左侧的应用管理 ---> 我的应用 ---->> 创建应用 1、创建应用 2、列表就会显示我们刚刚创建好的 key 3、点击添加 key 4、按照要求填写信息 我们用的是小程序 所以选择…

[python:django]:web框架搭建项目

文章目录 pip查看安装列表安装制定Django版本初始化django项目执行 python manage.py startapp projectName 生成app应用执行 python manage.py runserver 运行web项目配置django项目页面访问地址注意&#xff1a;再次访问地址&#xff0c;返回制定页面 pip查看安装列表 C:\Us…

通过 Java 操作 redis -- set 集合基本命令

目录 使用命令 sadd &#xff0c;smembers 使用命令 sismember 使用命令 scard 使用命令 spop 使用命令 sinter&#xff0c;sinterstore&#xff0c;sunion&#xff0c;sunionstore&#xff0c;sdiff&#xff0c;sdiffstore 关于 redis set 集合类型的相关命令推荐看Redis …