当前位置: 首页 > news >正文

【计算机网络】socket编程

文章目录

  • 1. 网络通信的理解
  • 2.进程PID可以取代端口号吗?
  • 3. 认识TCP协议
  • 4. 认识 UDP协议
  • 5. socket编程接口
    • udp_server.hpp的代码解析
      • socket——创建 socket 文件描述符
      • Initserver——初始化
        • 1.创建套接字接口,打开网络文件
          • bind——绑定的使用
        • 2.给服务器指明IP地址和端口号
          • struct sockaddr_in的理解
          • bzero 清空
          • 代码实现
          • inet_addr ——字符串风格转化为4字节风格
          • 服务器自己指定IP地址
        • 3. 云服务器,或者一款服务器,一般不要指明某一个确定的IP
      • start ——启动
        • 1. 收到客户端发来的消息
          • recvfrom——获取用户数据报
          • inet_addr ——将4字节风格转为字符串风格
        • 2.将消息发给别人
          • sendto
    • udp_client.cc的代码解析
      • 客户端如何绑定?
      • 服务器为什么要自己绑定?
      • 代码实现
    • 完整代码
      • err.hpp (枚举错误码)
      • makefile
      • udp_client.cc(客户端的实现,无封装)
      • udp_clinet.hpp
      • udp_server.cc (有封装)
      • udp_server.hpp(服务器的实现)

1. 网络通信的理解

主机A将自己的数据交给主机B,就需要给主机B发送消息,主机B未来要给主机A回消息

但实际上 主机A将自己的数据交给主机B 并不是最终目的

如:你在淘宝上买了一件衣服,卖家发货后,从广东省发货 到 你所在的地区 ,最终包裹成功到达你的手上,你还需要决定这个快递该怎么用

数据的传送不是目的,让两台主机通过数据进行通信来协同完成任务才是目的


如:唐僧说要去西天去取经,唐僧所对应的寺庙是A主机,西天的大雷音寺是B主机,唐僧并不是到大类饮食就完了,这只是他的手段,
他还需要面见如来,如来会提供给他经书的服务


数据发起时,从主机A的传输层开始,交给主机B的传输层
而数据是从主机A的应用层中的某种客户端传来的
而将数据交给主机B的传输层不是直接目的,要把数据再交给应用层 中的某种服务器

主机A对应的客户端一定要启动起来,所以其本质是 进程

因为主机B的某种服务器在以进程的方式运行,所以可以随时随地能够访问某种服务

网络通信的本质是 进程间的通信


通信的第一个阶段:先将数据通过操作系统,将数据发送到目标主机(手段)
通信的第二个阶段:在本主机将收到的数据,推送给自己上层的指定进程

第一个阶段 可以通过TCP/IP协议完成,因为IP可以表示互联网上唯一的一台主机

当主机B的传输层把数据交给应用层,应用层对应的进程非常多
所以为了标识自己主机上网络进程的唯一性,提出了 端口号 的概念

端口号是传输层协议的字段,是一个2个字节16位的整数,用来标识系统层面上进程的唯一性

所以 IP地址 + 端口号 可以表示 互联网中唯一的一个进程

通信时,是有两个进程进行通信,所以就有源IP 和源 端口号 以及 目标IP 和目标 端口号
源IP 和源 端口号表示 互联网中唯一的一个进程
目标IP 和目标 端口号也表示 互联网中唯一的一个进程

所以 网络通信的本质 是通过IP+PORT号 构建唯一性,来进行网络进程间通信, 简称 套接字通信

2.进程PID可以取代端口号吗?

进程PID在系统层面上每个进程也是唯一的,也能表示该系统上进程的唯一性,所以用进程PID可以代替端口号的
但会存在一些问题
1.不是所有的进程都要进行网络通信,只有部分进程可能会网络通信,若用进程PID来作为网络标识该进程,就很难区分清楚那些是进行网络通信的,那些不是进行网络通信的

2. PID是操作系统进程管理的概念,网络模块也要包含进程管理的部分,要不然无法认识PID
增加了系统当中进程管理和网络管理的耦合度

3. 认识TCP协议

TCP协议(Transmission Control Protocol) 传输控制协议
特点:
传输层协议
面向连接
在通信过程中,会自带可靠性
面向字节流
在进行发和收数据时,在TCP层没有报文的概念,收到一堆的数据,把这一堆的东西一次将给上层的应用层,也可一个字节一个字节交
字节数据如何解释TCP不关心,只关心要都多少,给你多少,最终解释信息由应用层自己解释,这种从称之为字节流

4. 认识 UDP协议

UDP协议(User Datagram Protocol)用户数据报协议
特点:
传输层协议
无连接
不可靠传输
面向数据报
如:收快递,收一个就是一个完整的快递,具体的快递不可能收半个或者一个半,若对方发了三次,你就必须收三次

5. socket编程接口

实验室做出来一套进程间通信的标准,既可在本地通信,又可以在网络跨主机通信的标准 即 socket标准 隶属于 posix标准

最常见的为 基于网络通信的套接字 sockaddr_in

预间套接字 (使用在两个进程间使用本地进程通信的) sockaddr_un

套接字的设计者为了能够让所有人以 一套接口的方式 既能本地通信 又能网络通信,
所以设计出一个公共的数据结构 叫做 struct sockaddr
若想进行网络通信 (struct sockaddr_in) 或者 进行 本地通信 (struct sockaddr_un) ,使用 sockaddr 进行强制转换即可


在结构最开始时,都要有16位的地址类型
AF_INET 与AF_UNIX 实际上都是宏,用整数来表示的
将地址进行比较判断,
若等于 AF_INET,就为网络通信,把 sockaddr强转为 sockaddr_in
若等于 AF_UNIX,就为本地通信,把 sockaddr强转为 sockaddr_un


udp_server.hpp的代码解析

通过网络协议栈的通信功能 ,来把数据交付给对方的应用层,来完成双方进程的通信

将客户端的数据交给 服务端 ,就需要给服务端发送消息,服务端再给客户端回消息


在 udp_server.hpp 中 使用namspace 将命名空间 命名为 ns_server
其中再定义一个类 udpserver

socket——创建 socket 文件描述符

输入 man socket创建套接字

第一个参数 domain ,用于区分 进行网络通信还是 本地通信
若想为网络通信,则使用 AF_INET
若想为本地通信,则使用 AF_UNIX

第二个参数 type, 套接字对应的服务类型

在这里插入图片描述

SOCK_STREAM 流式套接
SOCK_DGRAM 无连接不可靠的通信(用户数据报)

第三个参数 protocol ,表示想用那种协议,协议默认为0
若为 流式套接,则系统会认为是TCP协议 ,若为用户数据报,则系统会认为是UDP协议

套接字的返回值:若成功则返回文件描述符,若失败则返回 -1

Initserver——初始化

1.创建套接字接口,打开网络文件

在这里插入图片描述
使用socket套接字,创建出 网络通信、UDP协议
若套接字返回-1表示失败,则初始化也就失败,程序就没有必要在继续运行了,所以使用exit终止程序

若套接字创建成功,则返回文件描述符
文件描述符的前三个分别被 标准输入 标准输出 标准错误占用,所以此时的文件描述符应该打印出3

bind——绑定的使用

输入 man 2 bind ,查看绑定

给一个套接字绑定一个名字
第一个参数 sockfd 为 文件描述符
第二个参数 addr 为 通用结构体类型
第三个参数 addrlen 为 第二个参数的实际长度大小

bind返回值:若成功,则返回0,若失败,返回 -1

2.给服务器指明IP地址和端口号

想要使用struct sockaddr_in类型 需添加头文件

定义一个 struct sockaddr_in(网络通信) 类型的 变量 local

struct sockaddr_in的理解

在这里插入图片描述
将 struct sockaddr_in 转到定义
16位地址类型:将 sa_prefix替换成 sin_ ,sin## family 实际上为 sin_family
此时的 sin_port 对应 当前绑定的端口号
sin_addr对应的是IP地址
再次将 in_addr转到定义,IP地址就是一个32位的整数

bzero 清空

sin_zero 作为 该结构体的填充字段
结构体可能很大,用不完,则使用填充字段将其填充上即可

输入 man bzero

将有n个字节的缓冲区,全部写为0

代码实现

在这里插入图片描述

将local对应的family(16位地址类型) 设置为 网络通信


设置一个私有的端口号port_


在这里插入图片描述
在类外设置一个端口号,用于构造时,若没有端口号传入,则8082充当缺省值


若我给你发消息,未来也需要将消息发回来,所以就必须知道我的IP地址和端口号
即端口号 以报文的形式发送到网络中

类内定义的port_,被称为本地主机序列, 需要把这个port_从主机序列 转成网络序列

输入 man htons ,表示短整数的主机转网络序列



定义一个私有的变量 ip_ 由于我们设置的IP地址是字符串风格的,而系统中的IP地址是4字节风格的 所以就需要将字符串风格的转化为 4字节风格的
inet_addr ——字符串风格转化为4字节风格

输入 man inet_addr

作用为:将字符串风格的IP地址 转化为 4字节风格的IP地址,并 默认会把主机序列 转换为 网络序列


由于local实际上定义在用户层的栈上,并没有在内核

所以借助bind,将填充好的套接字字段和文件字段,进行绑定关联,这样的文件才是网络文件
由于local 是 struct sock_addr_in 类型 ,需要强转为 struct sockaddr 公共类型


服务器自己指定IP地址

此时运行 udp_server可执行程序,会发现套接字创建成功,但绑定会失败


云服务器 不需要bind IP地址,需要让服务器自己指定IP地址


所以在main函数中添加命令行参数
命令行参数
main函数的两个参数,char* argv[] 为指针数组 ,argv为一张表,包含一个个指针,指针指向字符串
int argc,argc为数组的元素个数

设计一个usage函数,用以表示出 出现问题的可执行程序的名字 proc


再次创建一个err.hpp,使用enum枚举,将USAGE_ERR设置成1 ,默认将SOCKET_ERR(套接字报错)设置为2,
将 BIND_ERR(绑定错误)设置为3


通过argv数组的第二个下标指明字符串风格的端口号,再通过atoi将字符串转化为整数
最终只传入 端口号即可


在这里插入图片描述

3. 云服务器,或者一款服务器,一般不要指明某一个确定的IP

在这里插入图片描述

使用 INADDDR_ANY , 让udpserver在启动的时候,bind本主机上的任意IP


将 INADDDR_ANY 转到定义,实际上为缺省的0值


start ——启动

服务器本质是一个死循环,永远不退出
如:半夜打开王者荣耀,依旧可以玩


1. 收到客户端发来的消息

recvfrom——获取用户数据报

输入 man recvfrom, 获取用户数据报

第一个参数 sockfd 为 套接字
第二个参数 buf 为 自己定义的缓冲区
第三个参数 len 为 缓冲区的长度
第四个参数 flags 为读取方式,默认设为0,以阻塞方式读取
剩余两个参数 src_addr 和 addrlen 为 输入 输出型 参数
使用recvfrom收到数据,最终还要把数据还回去,想要还回去就必须知道别人是谁
src_addr 为 作为一个结构体,内部记录客户端的IP地址和端口号
addrlen 为 输出时结构体的大小
返回值:若大于0,则读取成功


定义一个 struct sockaddr_in(网络通信) 类型的 变量 peer
使用 len 来表示 未来的结构体大小

若n大于0,则读取成功,将最后一个位置的下一个位置设为\0
若读取失败,则继续读取


peer下的IP地址为 4字节整数,需要将其转为字符串风格

inet_addr ——将4字节风格转为字符串风格

输入 man inet_addr,将4字节IP转为字符串风格的IP


peer下的端口号为网络序列,想要获取客户端的端口号 clientport,需要使用 ntohs 将网络序列转为主机序列

2.将消息发给别人

sendto

输入 man sendto

第一个参数 sockfd 为 套接字
第二个参数 buf 为 自己定义的缓冲区
第三个参数 len 为 缓冲区的长度
第四个参数 flags 为读取方式,默认设为0,以阻塞方式读取
剩余两个参数 src_addr 和 addrlen 为 输入 输出型 参数
使用recvfrom收到数据,最终还要把数据还回去,想要还回去就必须知道别人是谁
src_addr 为 将以前收到的消息转会给客户端
addrlen 为 输出时结构体的大小
返回值:若大于0,则读取成功



udp_client.cc的代码解析

第一个参数 使用 AF_INET,表示网络通信
第二个参数 使用SOCK_DRAM,表示数据报
第三个参数 默认设为0,由于上述为数据报,所以为UDP协议


客户端如何绑定?

客户端是需要绑定的
socket通信的本质 是 客户端的IP与端口号 与 服务器的IP与端口号 进行网络版本的进程间通信
但客户端是不需要自己绑定的,由操作系统自动进行绑定
如:电脑和手机充满大量客户端,这些客户端来自于不同的企业,每个客户端的端口号不可以是固定的
必须让操作系统随机去选择,本质是为了防止确定的客户端被别人去占用,减少客户端层面的冲突
所以客户端的端口号要让操作系统随机分配,防止客户端出现启动冲突

服务器为什么要自己绑定?

1.服务器的端口 是 众所周知并不能随意改变的
如:110是报警电话,不可能报警电话每天都变,否则会导致当真正想打电话时都不知道打那个

2.服务器都是一家公司的,所以端口号需要统一规范化
如:淘宝不会把自己的服务部署到知乎上


代码实现

进行while循环,向服务器发送消息

目前没有消息,所以让用户输入充当消息源
使用 sendto,将消息发送给服务端

作为客户端将消息发送给 服务器主机
想要运行 客户端 ,就需要服务器的IP 和端口号


在这里插入图片描述
借助命令行参数,通过用户的输入的第二个参数 作为服务器的IP
用户输入的第三个作为 服务器的端口号

虽然此时服务器的IP和端口号知道了,但是想要借助sendto,后两个参数是需要套接字结构体


新建一个结构体server,内部包含服务器的IP和端口号
使用 htons ,将主机序列转为网络序列
使用inet_addr,将字符串转化为 4字节


在这里插入图片描述

此时 sendto的后两个参数 添加 创建的结构体 sever ,来完成发送服务器的任务
由于server 的类型 是 struct sockaddr_in ,而参数的类型为 公共结构体类型 struct sockaddr ,所以需要强转


使用 revfrom ,获取用户数据报
收到来自服务器转回来的消息 ,所以 定义一个 temp结构体,用于接收

在首次系统调用发送数据的时候,操作系统在底层随机选择客户端的端口号 加上自己的IP
先构建bind,再构建发送的数据报文

完整代码

err.hpp (枚举错误码)

#pragma onceenum 
{USAGE_ERR=1,SOCKET_ERR,BIND_ERR
};

makefile

.PHONY:all
all: udp_client udp_serverudp_client:udp_client.ccg++ -o  $@ $^ -std=c++11
udp_server:udp_server.ccg++ -o $@  $^ -std=c++11.PHONY:clean
clean:rm -f udp_clinet udp_server

udp_client.cc(客户端的实现,无封装)

#include"udp_client.hpp"
#include"err.hpp"
#include<cstring>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>static void usage(std::string proc)
{std::cout<<"usage:\n\t"<<proc<<"serverip serverport\n"<< std::endl;
}
// ./udp_client serverip sevrerport
int main(int argc ,char* argv[])//命令行参数 传入的是 客户端的运行 服务器的IP和端口号
{if(argc!=3){std::cout<<" "<<std::endl;exit( USAGE_ERR);//终止程序}std::string serverip = argv[1];//服务器的IPuint16_t serverport =atoi(argv[2]);//服务器的端口号int sock=socket(AF_INET,SOCK_DGRAM,0);if(sock<0)//创建套接字失败{std::cout<<"create socket error"<<std::endl;exit( SOCKET_ERR);}//明确server是谁struct sockaddr_in server;//设置网络通信的结构体memset(&server,0,sizeof(server)); //将结构体清空server.sin_family=AF_INET;server.sin_port=htons(serverport);//端口号server.sin_addr.s_addr=inet_addr(serverip.c_str());//IP地址while(true){//用户输入  std::string message;std::cout<<  "please enter# ";std::cin>> message;//发送消息sendto(sock,message.c_str(),message.size(),0,(struct sockaddr*)&server,sizeof(server));//接收消息char buffer[1024];struct sockaddr_in temp;socklen_t len=sizeof(temp);int n=recvfrom(sock,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&temp,&len);if(n>0){buffer[n]=0;//收到回显消息std::cout<<"server echo"<<buffer<<std::endl;}}return 0;
}

udp_clinet.hpp

#pragma once
#include<iostream>
using namespace std;

udp_server.cc (有封装)

#include"udp_server.hpp"
#include"err.hpp"
#include<memory>
#include<string>
using namespace ns_server;
using namespace std;static void usage(string proc)
{std::cout<<"usage:\n\t"<<proc<<"prot\n"<< std::endl;
}//udp_server port
int main(int argc,char*argv[])//命令行参数
{if(argc!=2)//若命令行参数个数不为2,则当前会报错{usage(argv[0]);exit(USAGE_ERR);//终止程序}//端口号uint16_t port=atoi(argv[1]);//atoi可将字符串转化为整数//只需传入由用户指明的端口号unique_ptr<UdpServer> usvr(new UdpServer (port));usvr->Initserver();//服务器的初始化usvr->Start();//启动服务器return 0;
}

udp_server.hpp(服务器的实现)

#pragma once
#include<iostream>
#include<cerrno>
#include<cstring>
#include<cstdlib> 
#include<strings.h>
#include<functional>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include"err.hpp"namespace  ns_server
{const static uint16_t  default_port=8082;//设置端口号为8082 class UdpServer{public:UdpServer(uint16_t port=default_port)//构造:port_(port){}void  Initserver()//初始化{//1.创建套接字接口,打开网络文件sock_=socket(AF_INET,SOCK_DGRAM,0);if(sock_<0)//创建失败{//打印错误信息std::cout<<" create socket   error: "<<strerror(errno)<<std::endl;exit(SOCKET_ERR);//终止程序}std::cout<<"create socket success:"<<sock_<<std::endl;//3//2.给服务器指明IP地址和端口号struct sockaddr_in local;bzero(&local,sizeof(local));//全部置为0local.sin_family=AF_INET;//将16位地址类型 置为 网络通信local.sin_port=  htons(port_); //主机转网络的端口号//1.需要将字符串风格转化为 4字节//2.需要 将主机序列转换为 网络序列local.sin_addr.s_addr= INADDR_ANY ; //bind本机上的任意IP//bind 绑定int n=bind(sock_,(struct sockaddr*)&local,sizeof(local));if(n<0)//绑定失败{std::cout<<" bind  socket   error: "<<strerror(errno)<<std::endl;exit(BIND_ERR);}std::cout<<"bind socket success:"<<sock_<<std::endl;//3}void Start()//启动{char buffer[1024];//用于保护用户数据//设置一个死循环while(true){//1.收到客户端发来的消息struct sockaddr_in peer;socklen_t len=sizeof(peer);//传入的缓冲区大小int n=recvfrom(sock_,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);if(n>0){buffer[n]='\0';}else {//读取失败,则继续读取continue;}//提取客户端信息//4字节IP转为 字符串IPstd::string clientip =inet_ntoa(peer.sin_addr);//客户端IP//将网络序列转换为主机序列uint16_t clientport =ntohs(peer.sin_port);//客户端 端口号std::cout<<clientip<<"-"<<clientport<<"-"<<"get message# "<<buffer<<std::endl;//2.将消息发给别人sendto(sock_,buffer,strlen(buffer),0,(struct sockaddr*)&peer,sizeof(peer));}}~UdpServer()//析构{}private:int sock_; //文件描述符uint16_t port_;//端口号 }; 
}

相关文章:

【计算机网络】socket编程

文章目录 1. 网络通信的理解2.进程PID可以取代端口号吗&#xff1f;3. 认识TCP协议4. 认识 UDP协议5. socket编程接口udp_server.hpp的代码解析socket——创建 socket 文件描述符Initserver——初始化1.创建套接字接口&#xff0c;打开网络文件bind——绑定的使用 2.给服务器指…...

2023华为OD机试真题 Python 实现【寻找最大价值的矿堆/深度优先搜索】

前言 本题使用Python解答,如果需要Java代码,请点击以下链接:点我 题目 我们规定,0表示空地,1表示银矿、2表示金矿,矿堆表示由相邻的金矿或银矿连接形成的地图。 银矿价值是1 ,金矿价值是2 ,你的目标是找出地图中最大价值的矿堆,并且输出该矿堆的价值 示例1 输入:…...

【Java面试】Nacos自动注册原理实现以及服务注册更新并如何保存到注册表

文章目录 Nacos自动注册原理实现服务注册更新并如何保存到注册表 Nacos自动注册原理实现 完整流程 我们知道SpringBoot提供了挂载点的方式来帮助我们的类完成自动注入。 Nacos再META-INF的spring.factories这个文件中添加了自己需要自动注入的Bean对象。 叫做NacosServiceRegi…...

linux 手动编译安装 pkg-config 步骤

1. 下载源码 Index of /releases (pkg-config.freedesktop.org) 2. 解压 并 进入解压后的文件夹 3. 运行配置文件 ./configure 错误解决办法&#xff1a;在linux中使用 ./configure 时报错 4. 编译、 自检、 安装 make make check make install 5. 安装完成后查看版本号…...

【MongoDB】数据库、集合、文档常用CRUD命令

目录 一、数据库操作 1、创建数据库操作 2、查看当前有哪些数据库 3、查看当前在使用哪个数据库 4、删除数据库 二、集合操作 1、查看有哪些集合 2、删除集合 3、创建集合 三、文档基本操作 1、插入数据 2、查询数据 3、删除数据 4、修改数据 四、文档分页查询 …...

【JVM】是如何管理内存的

文章目录 JVM 内存管理 模型JVM内存管理示例解析jvm 常见优化手段 JVM 内存管理 模型 以下是JVM内存管理的详细图示&#xff1a; ------------------------------------------------------ | Java 运行时数据区 | ------…...

进程与线程、线程创建、线程周期、多线程安全和线程池(ThreadPoolExecutor)

目录 进程与线程线程和进程的区别是什么&#xff1f;线程分两种&#xff1a;用户线程和守护线程线程创建四种方式run()和start()方法区别&#xff1a;为什么调用 start() 方法时会执行 run() 方法&#xff0c;为什么不能直接调用 run() 方法&#xff1f;Runnable接口和Callable…...

《论文阅读13》Efficient Urban-scale Point Clouds Segmentationwith BEV Projection

一、论文 研究领域&#xff1a; 城市级3D语义分割论文&#xff1a;Efficient Urban-scale Point Clouds Segmentationwith BEV Projection论文链接 注&#xff1a; BEV&#xff1a; Birds Eye View BEV投影是指鸟瞰视角(Birds Eye View,简称BEV)的一种从上方观看对象或场景的…...

Django实现音乐网站 ⑻

使用Python Django框架制作一个音乐网站&#xff0c; 本篇主要是后台对单曲原有功能的基础上进行部分功能实现和显示优化。 目录 新增编辑 歌手下拉显示修改 设置歌曲时长 安装eyed3库 获取mp3时长 歌曲时长字段修改 重写save方法 增加歌手单曲数量 查询歌手单曲数量 …...

VScode中同时打开两个脚本

使用快捷键&#xff1a; CtrlAltRightArrow 效果&#xff1a; 可以看到&#xff0c;上述两个脚本使用独立的窗口进行编辑和查看。...

能源电力工程师专属Python学习资料

随着我国新型电力系统的建设&#xff0c;一方面电源侧各类新能源装机快速增长&#xff0c;对于新能源出力的功率预测需求日益增长&#xff1b;另一方面&#xff0c;我国电力市场经过 8 年建设&#xff0c;关于电力商品价格影响因素的研究亟待深入。超过 90% 的业务小伙伴都具备…...

推荐5款实用软件,提高工作效率,丰富生活乐趣

​ 分享软件会让我感到开心和满足&#xff0c;因为我知道这些软件可以提高工作效率,丰富生活乐趣。今天再次将几款非常实用的软件推荐给大家。 截图翻译工具——CopyTranslator ​ CopyTranslator是一款非常实用的截图翻译软件,它支持对截图、选定区域进行OCR文字识别,自动翻…...

Python爬虫在电商数据挖掘中的应用

作为一名长期扎根在爬虫行业的专业的技术员&#xff0c;我今天要和大家分享一些有关Python爬虫在电商数据挖掘中的应用与案例分析。在如今数字化的时代&#xff0c;电商数据蕴含着丰富的信息&#xff0c;通过使用爬虫技术&#xff0c;我们可以轻松获取电商网站上的产品信息、用…...

element-ui 表格el-table的列内容溢出省略显示,鼠标移上显示全部和定制样式

1、在对应列加上省略显示show-overflow-tooltip属性&#xff0c;如果加上这属性&#xff0c;鼠标移上还是没效果&#xff0c;要考滤是不是层级的原因&#xff0c;被其他挡住了。 :deep(.el-tooltip){position: relative;z-index:9; } <el-table-column label"用款渠…...

研究人员发现特斯拉汽车能被越狱,可免费解锁付费功能

Bleeping Computer 网站披露&#xff0c;柏林工业大学&#xff08;Technical University of Berlin&#xff09;的研究人员开发出一种新技术&#xff0c;可以破解特斯拉近期推出所有车型上使用的基于 AMD 的信息娱乐系统&#xff0c;并使其运行包括付费项目在内的任何软件。 实…...

【设计模式】责任链的基本概念及使用Predicate灵活构造校验链

文章目录 1. 概述1.1.背景1.2.责任链模式的概念 2.责任链的基本写法2.1.链表实现2.2.数组实现 3.Predicate校验链2.1.使用Predicate改写代码2.1.更丰富的条件拓展 4.总结 1. 概述 1.1.背景 在最近的开发中遇到了这么一个需求&#xff0c;需要对业务流程中的各个参数做前置校验…...

Taro保存图片到手机

萌新亚历山大啊&#xff0c;搞了一下午&#xff0c;真多坑 Taro.downloadFile({url: res,filePath: Taro.env.USER_DATA_PATH /xcxcode.jpg,success: res > {if (res.statusCode 200) {console.log(res)const tempFilePath res.filePath; // 获取下载的临时文件路径// …...

zookeeper --- 基础篇

一、zookeeper简介 1.1、什么是zookeeper zookeeper官网&#xff1a;https://zookeeper.apache.org/ 大数据生态系统里的很多组件的命名都是某种动物或者昆虫&#xff0c;他是用来管 Hadoop&#xff08;大象&#xff09;、Hive(蜜蜂)、Pig(小 猪)的管理员。顾名思义就是管理…...

Golang map 常用方法

文章目录 前言按key排序按value排序统计字符串中元素重复出现次数并将结果排序返回 前言 由于map是无序的&#xff0c;所以排序成 slice 返回&#xff0c;且都使用泛,代码只是示例&#xff0c;省略了错误判断 按key排序 package mainimport "fmt"func example[T c…...

用于视觉跟踪的在线特征选择研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...