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

【Linux网络编程三】Udp套接字编程网络应用场景

【Linux网络编程三】Udp套接字编程网络应用场景

  • 应用场景一:远程命令执行
  • 应用场景二:与Windos端相互通信
  • 应用场景三:简单聊天
    • 1.多线程化
    • 2.输入输出分开

应用场景一:远程命令执行

简单的服务器上一篇已经完成,接下来我,们就可以加一些应用场景了。我们知道客户端发送消息给服务器,服务器对消息加工处理再发送回去。但谁规定客户端只能发送消息的呢?我们可以发送一些命令,让服务帮我执行,然后将执行结果再发送回来。

服务器的对数据的加工处理动作是可以分离出来的,实现代码层面的分层。
通过函数回调的方法,由上层来决定加工处理动作。
在这里插入图片描述

所以我们只需要在服务器内部定义一个函数指针,将客户端发送的数据传递给函数。调用该函数,由上层传入函数来实现回调。

所以我们想实现对客户端佛发送的命令进行执行,然后将执行结果再发送回去。

在这里插入图片描述
我们利用popen()这个系统调用接口。它可以将传递进行的以字符串形式的命令,通过程序替换的形式执行。并且是自动创建子进程,让子进程程序替换,并且创建父子管道,将执行的结果通过管道返回回来。
返回的结果存放在一个文件里,我们可以通过文件描述符来访问。
在这里插入图片描述


#include "Udpserver.hpp"
#include <memory>
#include <cstdio>
#include <stdlib.h>std::string ExcuteCommand(const std::string& cmd)
{std::cout<<"get a request cmd: "<<cmd<<std::endl;//服务器端接收到命令后,会先打印获取到一个命令//获取到命令后,就让服务器进行运行处理FILE* fp=popen(cmd.c_str(),"r");//popen会自动创建子进程,让子进程进行程序替换,运行字符串命令,然后会建立父子间的管道,将运行结果发送给父进程if(fp==nullptr){perror("popen");return "error";}std::string reslut;char buffer[1024];while(true){char*r=fgets(buffer,sizeof(buffer),fp);//按行读取,读取一行if(r==nullptr)break;reslut+=r;}pclose(fp);return reslut;
}
*/
#include "Udpserver.hpp"
#include <memory>
#include <cstdio>void Usage(std::string proc)
{std::cout<<"\n\rUsage: "<<proc<<" port[1024+]\n"<<std::endl;
}
//服务器进程,启动时,按照./Udpserver+port的形式传递
int main(int args,char* argv[])
{if(args!=2){Usage(argv[0]);exit(0);}uint16_t port=std::stoi(argv[1]);std::unique_ptr<Udpserver> svr(new Udpserver(port));//首先创建一个服务器对象指针//智能指针,用一个UdpServer指针来管理类对象svr->Init();//初始化服务器svr->Run(ExcuteCommand);//启动服务器return 0;
} 

在这里插入图片描述

通过这个场景,我们就应该能够理解Xshell的本质就是一个客户端,而启动时连接ip登入密码就是在连接服务器。然后我们输入的命令,将发送给xhell服务器,然后服务器将执行结果再发送给我们。
在这里插入图片描述

应用场景二:与Windos端相互通信

我们在Linux下写的网络通信其实在window下也是可以进行通信的,虽然两个操作系统不同,但是网络协议栈是相同的,所以它们是具有相同的接口的。
只不过在Windows下还需要几个windows库要使用,其他的都跟linux下是一样的。所以我们是可以在Linux下和Windows下互相通信的,让linux下程序充当服务器,让windows下的程序充当客户端。

在这里插入图片描述
以上就是在windows下通信需要的准备工作,需要包含一个新的头文件,要注意必须先包含该头文件,在包含下面的lib32库。
然后对库进行初始化。最后不使用了就关闭库。中间就是我们的网络通信部分。

这里还有一个细节,就是在windows下,将字符转换成int字节的函数inet_pton()会显示没有定义吗,但是是定义成功的,所以我们选择忽略这个警告:
在这里插入图片描述

【Windows下的客户端】


#include <iostream>
#include <WinSock2.h>
#include <Windows.h>
#include <cstdlib>
#include <cstdio>
#include <string>
#pragma comment(lib,"ws2_32.lib")#pragma warning(disable:4996)
std::string serverip = "112.124.70.128";
//一般app客户端内置服务器的ip地址,这里我们就直接连接我们的linux服务器ip地址
uint16_t serverport = 3555;
int main()
{WSADATA wsd;WSAStartup(MAKEWORD(2, 2), &wsd);struct sockaddr_in server;memset(&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_addr.s_addr = inet_addr(serverip.c_str()); // 将string类型转换成int类型,并且是网络字节序//在windos下回存在警告,忽略即可server.sin_port = htons(serverport);int len = sizeof(server);// 1.创建套接字---本质就是打开网络文件int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd ==SOCKET_ERROR ){std::cout << "socket create err" << std::endl;return 1;}// 创建成功// 2.需要绑定吗?系统会给我自动绑定,首次发送的时候就会绑定// 3.往服务器的套接字里发送消息--需要知道服务器的ip和端口号,目的ip和目的port,将ip和port填入结构体对象里char outbuffer[1024];std::string message;while (true){std::cout << "Please enter@ ";std::getline(std::cin, message);//1.发送给服务器sendto(sockfd, message.c_str(), message.size(), 0, (const struct sockaddr*)&server, len);struct sockaddr_in temp;int l = sizeof(temp);//2.接收服务器的应答int s = recvfrom(sockfd, outbuffer, 1023, 0, (struct sockaddr*)&temp, &l);if (s > 0){//接收成功outbuffer[s] = 0;std::cout << outbuffer << std::endl;}}//close(sockfd);closesocket(sockfd);WSACleanup();return 0;
}

在这里插入图片描述
Linux和windows下的编码不同所以在windows下接收linux下加工的消息就会存在不同。
【Linux下的服务器】

@ -0,0 +1,103 @@
#pragma once#include "Log.hpp"
#include <iostream>
#include <string>
#include <strings.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <functional>
std::string defaultip = "0.0.0.0";
uint16_t defaultport = 8080;
Log lg; // 日志,默认往显示屏打印
typedef std::function<std::string(const std::string&)> func_t;//相当于定义了一个函数指针
//返回值是string类型,函数参数也是string类型,利用函数回调的方法,将服务器端对数据的处理操作进行分离,由上层传递的函数来决定如何处理
enum
{SOCKET_ERR = 1,BIND_ERR
};
class Udpserver
{
public:Udpserver(const uint16_t &port = defaultport, std::string &ip = defaultip) : _sockfd(0), _port(port), _ip(ip){}void Init(){// 1.创建udp套接字,本质就是打开网络套接字文件_sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd < 0) // 表示创建失败{lg(Fatal, "socket create error,socket: %d", _sockfd);exit(SOCKET_ERR); // 创建失败之间退出}// 创建成功lg(Info, "socket create success,socket: %d", _sockfd);// 2.绑定服务器的套接信息,比如ip和端口号// 在绑定套接信息之前,需要先将对应的结构体对象填充完毕sock_addrstruct sockaddr_in local;                       // 网络通信类型bzero(&local, sizeof(local));                   // 将内容置为0local.sin_family = AF_INET;                     // 网络通信类型local.sin_port = htons(_port);                  // 网络通信中,端口号需要不断发送,所以需要符合网络字节序,主机--->网络字节序local.sin_addr.s_addr = inet_addr(_ip.c_str()); // 需要将string类型的ip转换成int类型,并且还需要满足网络字节序的要求socklen_t len = sizeof(local);// 以上只是将要绑定的信息填充完毕,套接字(网络文件)而还没有绑定套接信息if (bind(_sockfd, (const struct sockaddr *)&local, len) < 0) // 绑定失败{lg(Fatal, "bind sockfd error,errno:%d,err string:%s", errno, strerror(errno));exit(BIND_ERR);}lg(Info, "bind sockfd success,errno:%d,err string:%s", errno, strerror(errno)); // 绑定成功}void Run(func_t func) // 服务器是一旦启动不会退出,服务器接收消息,并发送答应{// 1.接收信息char buffer[SIZE];while (true){struct sockaddr_in client;socklen_t len = sizeof(client);// 服务器接收到消息,它还需要知道谁给它发送的,为了后续将应答返回过去// 利用一个输出型参数,将对方的网络信息填充到里面ssize_t n = recvfrom(_sockfd, buffer, sizeof(buffer)-1, 0, (struct sockaddr *)&client, &len);if (n < 0){lg(Warning, "recvfrom sockfd err,errno: %d, err string %s", errno, strerror(errno));continue;}// 读取成功,将网络文件里的消息读取到buffer里buffer[n] = 0; // 字符串形式// 2.加工处理// std::string info = buffer;// std::string echo_string  = "server echo# " + info;std::string info=buffer;std::string echo_string=func(info);//将接收的信息由外层函数进行处理// 3.将应答发送回去// 发送给谁呢?服务器知道吗?服务器知道!因为在接收消息时,服务器就用一个输出型参数,将客户端的网络消息保存下来了sendto(_sockfd, echo_string.c_str(), echo_string.size(), 0, (const struct sockaddr *)&client, len);}}~Udpserver(){if (_sockfd > 0)close(_sockfd);}private:int _sockfd;     // 套接字文件描述符std::string _ip; // 我们习惯用string类型的ip地址uint16_t _port;  // 服务器进程的端口号
};

应用场景三:简单聊天

我们还可以制作一个简单的聊天软件,平常我们往群里输入一个消息,qq群里上就会显示我发送了一条消息。并且还标明了是谁发送的。比如李四往群里发送:“hello world”。群里的人都能看到这条消息:李四:“hello world”。

当客户端给服务器发送消息时,服务器不仅能接收到客户端发送的内容,还可以知道客户端的网络消息(客户端的ip和端口号等),也就是知道是谁发送它。所以这里我们可以利用ip+端口号来表示用户。当用户往服务器发送消息时,服务器就将该用户的ip地址+端口号来表示该用户,然后将以[ip+port]:消息再发送回去。显示在屏幕上。
在这里插入图片描述

注意:客户端发送消息给服务器,服务器可以获取到客户端的ip地址和端口号等网络信息,但这些信息都是网络字节序的,如果服务器想使用,需要先转换成用户字节序的。
1.可以使用ntohs()接口将端口号从网络字节序转用户字节序
2.可以使用inet_ntoa()将int类型的ip地址转string类型的ip地址,并转换成用户字节序。

还有就是我往群里发送的消息,qq群里的人是不是都能看到呀。所以我们应该让所有连接服务器的客户端用户都能看到我发送的消息。而他们往群里发送的消息,我也可以看到。

所以我们需要将所有在线的客户端都能看到消息,我们需要制作一个在线用户列表。
我们用一个哈希表来存储在线用户。当客户端用户发送消息时,服务器端就会接收消息,根据用户的ip地址来到哈希表里检测,哈希表里是否有该用户,如果没有,就添加进去,如果有则什么都不做。这样就将用户添加到哈希表里了,所有发送过消息的客户端用户都会被添加进去,但是同一个ip的只能添加一个客户端。
在这里插入图片描述

服务器接收消息,并加工处理后,就可以发送给所有在线的客户端用户了,广播发送给所有用户,那么这些用户在哪呢?在哈希表里!(只要有新客户端用户发送消息了,就会将该客户端ip添加到哈希表里,哈希表kv结果,k表示ip地址,v表示客户端的网络信息)

在这里插入图片描述

#pragma once#include "Log.hpp"
#include <iostream>
#include <string>
#include <strings.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <functional>
#include <unordered_map>
std::string defaultip = "0.0.0.0";
uint16_t defaultport = 8080;
Log lg;                                                                                                   // 日志,默认往显示屏打印
typedef std::function<std::string(const std::string &info, uint16_t &port, const std::string ip)> func_t; // 相当于定义了一个函数指针
// 返回值是string类型,函数参数也是string类型,利用函数回调的方法,将服务器端对数据的处理操作进行分离,由上层传递的函数来决定如何处理
enum
{SOCKET_ERR = 1,BIND_ERR
};
class Udpserver
{
public:Udpserver(const uint16_t &port = defaultport, std::string &ip = defaultip) : _sockfd(0), _port(port), _ip(ip){}void Init(){// 1.创建udp套接字,本质就是打开网络套接字文件_sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd < 0) // 表示创建失败{lg(Fatal, "socket create error,socket: %d", _sockfd);exit(SOCKET_ERR); // 创建失败之间退出}// 创建成功lg(Info, "socket create success,socket: %d", _sockfd);// 2.绑定服务器的套接信息,比如ip和端口号// 在绑定套接信息之前,需要先将对应的结构体对象填充完毕sock_addrstruct sockaddr_in local;                       // 网络通信类型bzero(&local, sizeof(local));                   // 将内容置为0local.sin_family = AF_INET;                     // 网络通信类型local.sin_port = htons(_port);                  // 网络通信中,端口号需要不断发送,所以需要符合网络字节序,主机--->网络字节序local.sin_addr.s_addr = inet_addr(_ip.c_str()); // 需要将string类型的ip转换成int类型,并且还需要满足网络字节序的要求socklen_t len = sizeof(local);// 以上只是将要绑定的信息填充完毕,套接字(网络文件)而还没有绑定套接信息if (bind(_sockfd, (const struct sockaddr *)&local, len) < 0) // 绑定失败{lg(Fatal, "bind sockfd error,errno:%d,err string:%s", errno, strerror(errno));exit(BIND_ERR);}lg(Info, "bind sockfd success,errno:%d,err string:%s", errno, strerror(errno)); // 绑定成功}void Checkuser(struct sockaddr_in &client,uint16_t &clientport,const std::string &clientip){//用该ip检测哈希表里是否存在该用户auto iter=online_user.find(clientip);if(iter==online_user.end())//说明没有找到, 是新用户{online_user.insert({clientip,client});std::cout<<"add a user"<<":["<<clientip<<":"<<clientport<<"]"<<std::endl; }//如果不是新用户,那么什么都不干}void Broadcast(const std::string info,uint16_t &clientport,const std::string &clientip){//将消息加工处理广播发送给所有在线的用户,而这些用户都在哈希表里for(auto& user:online_user){std::string message="[处理客户端数据 ";message+=clientip;message+=":";message+=std::to_string(clientport);message+="]";message+=info;sendto(_sockfd, message.c_str(), message.size(), 0, (const struct sockaddr *)&(user.second), sizeof(user.second));}}void Run(/*func_t func*/) // 服务器是一旦启动不会退出,服务器接收消息,并发送答应{// 1.接收信息char buffer[SIZE];while (true){struct sockaddr_in client;socklen_t len = sizeof(client);// 服务器接收到消息,它还需要知道谁给它发送的,为了后续将应答返回过去// 利用一个输出型参数,将对方的网络信息填充到里面ssize_t n = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&client, &len);if (n < 0){lg(Warning, "recvfrom sockfd err,errno: %d, err string %s", errno, strerror(errno));continue;}// 读取成功,将网络文件里的消息读取到buffer里buffer[n] = 0; // 字符串形式// 服务器想知道是谁给它发送消息的//①获取到发送者的消息②也获取到发送者的套接字信息,所以我们怎么知道是谁发送过来的呢?uint16_t clientport = ntohs(client.sin_port);      // 注意port是网络字节序,需要转成用户字节序std::string clientip = inet_ntoa(client.sin_addr); // ip是网络字节序的int类型,需要转换成string类型Checkuser(client,clientport,clientip);//在线用户列表 std::string info = buffer;//接收消息后,就广播发送给所有在线的人,并告诉是谁发送的Broadcast(info,clientport,clientip);// std::string info = buffer;// std::string echo_string  = "server echo# " + info;// std::string info=buffer;// std::string echo_string=func(info,clientport,clientip);// 将接收的信息由外层函数进行处理// 3.将应答发送回去// 发送给谁呢?服务器知道吗?服务器知道!因为在接收消息时,服务器就用一个输出型参数,将客户端的网络消息保存下来了//sendto(_sockfd, echo_string.c_str(), echo_string.size(), 0, (const struct sockaddr *)&client, len);}}~Udpserver(){if (_sockfd > 0)close(_sockfd);}private:int _sockfd;     // 套接字文件描述符std::string _ip; // 我们习惯用string类型的ip地址uint16_t _port;  // 服务器进程的端口号std::unordered_map<std::string, struct sockaddr_in> online_user; // 网上在线列表// 服务器收到一个客户信息,就要检测这个客户是不是新用户,如果是就添加进去
};

1.多线程化

不过客户端是存在问题的,什么问题呢?用户是不是也能看到别人发送的消息?
是的,但是目前的客户端要求用户必须先输入,才能获取服务器发送的消息,也就是我不输入,也就看不到别人的消息。只有我输入了。而正常聊天应该是,我不输入,我也能看到对方发送的消息应该。
这就要求,输入和输出两个动作要同时运行,我们可以使用多线程,让两个线程各自执行,一个线程执行发送,一个线程执行读取,这样,就算我输入,也能接收到别人发送的消息。

在这里插入图片描述

【理论依据】:在这里插入图片描述

在这里插入图片描述
发送线程需要往套接字里发送,并且需要知道发送给谁,所以需要构建一个结构体对象封装套接字,和服务器网络信息。
接收线程需要从套接字里读取。通过结构体对象里的套接字。
所以我们可以利用该结构来作为线程函数的参数。让线程拿到。在之前先将内容初始填充。

在这里插入图片描述


#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>using namespace std;#include <iostream>
#include <strings.h>
#include <sys/types.h>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>using namespace std;
// 客户端
void Usage(std::string proc)
{std::cout << "\n\r./Usage: " << proc << " serverip serverport\n"<< endl;
}struct PthreadData
{int sockfd;struct sockaddr_in server;
};
void *Sender(void *args)
{while (true){PthreadData *pd = static_cast<PthreadData *>(args);socklen_t len = sizeof(pd->server);string message;cout << "Please enter@ ";getline(cin, message);// 1.发送给服务器sendto(pd->sockfd, message.c_str(), message.size(), 0, (const struct sockaddr *)&(pd->server), len);}
}
void *Revcer(void *args)
{while (true){PthreadData *pd = static_cast<PthreadData *>(args);char outbuffer[1024];struct sockaddr_in temp;socklen_t l = sizeof(temp);// 2.接收服务器的应答ssize_t s = recvfrom(pd->sockfd, outbuffer, 1023, 0, (struct sockaddr *)&temp, &l);// 共用一个套接字,但不影响,是线程安全的if (s > 0){// 接收成功outbuffer[s] = 0;cerr << outbuffer << endl;}}
}
// 启动客户端时要求是: ./Client 服务器ip 服务器port
int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);exit(0);}std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);PthreadData pd;bzero(&(pd.server), sizeof(pd.server));pd.server.sin_family = AF_INET;pd.server.sin_addr.s_addr = inet_addr(serverip.c_str()); // 将string类型转换成int类型,并且是网络字节序pd.server.sin_port = htons(serverport);// 1.创建套接字---本质就是打开网络文件pd.sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (pd.sockfd < 0){cout << "socket create err" << endl;return 1;}// 创建成功// 2.需要绑定吗?系统会给我自动绑定,首次发送的时候就会绑定// 3.往服务器的套接字里发送消息--需要知道服务器的ip和端口号,目的ip和目的port,将ip和port填入结构体对象里pthread_t sender, revcer;pthread_create(&sender, nullptr, Sender, &pd);pthread_create(&revcer, nullptr, Revcer, &pd);pthread_join(sender, nullptr);pthread_join(revcer, nullptr);close(pd.sockfd);return 0;
}

这样一个线程一直在读取,只要有人往套接字里发送消息了,服务器就能直接返回回来,我就可以获取到,不需要输入就可以获取到。因为另一个线程在输入。两个线程是并发的。
在这里插入图片描述

2.输入输出分开

上面还存在一个问题:输入和输出混乱,在同一个显示屏里混乱输出。体验感不好。
所以我们想让输入和输出分开显示。怎么做呢?通过终端!通过打开多个终端,让输入输出显示在不同的终端上。
在这里插入图片描述

首先就是让服务器端加工处理后的数据,利用错误输出流输出。而客户端发送消息默认输出在当前显示屏上。
然后再二号错误输出流重定向到一个新打开的终端显示器上。这样最后服务器发送回来的消息就会显示在新打开的终端上。而客户端输出,就默认输入在旧的终端。在这里插入图片描述

在这里插入图片描述

相关文章:

【Linux网络编程三】Udp套接字编程网络应用场景

【Linux网络编程三】Udp套接字编程网络应用场景 应用场景一&#xff1a;远程命令执行应用场景二&#xff1a;与Windos端相互通信应用场景三&#xff1a;简单聊天1.多线程化2.输入输出分开 应用场景一&#xff1a;远程命令执行 简单的服务器上一篇已经完成&#xff0c;接下来我…...

计算机网络实验二

目录 实验二 交换机的基本配置 1、实验目的 2、实验设备 &#xff08;1&#xff09;实验内容&#xff1a; &#xff08;2&#xff09;练习&#xff1a; 1.实验内容一&#xff1a;&#xff08;交换机的配置方式&#xff09; 2.实验内容二&#xff1a;&#xff08;交换机…...

PS一键磨皮插件Delicious Retouch for mac中文 支持PS2024

Delicious Retouch for Mac是一款优秀的Photoshop插件&#xff0c;专注于人像修饰。以下是该插件的一些主要特点和功能&#xff1a; 软件下载&#xff1a;Delicious Retouch for mac中文 支持PS2024 人像修饰工具&#xff1a;Delicious Retouch专注于人像修饰&#xff0c;提供了…...

信息安全管理措施

本文已收录至《全国计算机等级考试——信息 安全技术》专栏 目的 信息是企业存在和发展的重要基础。为规范企业信息管理&#xff0c;保障信息安全&#xff0c;明确信息安全管理的程序、职责、义务和权限&#xff0c;特制定本制度。 职责 网络管理员&#xff08;委外&#xf…...

『运维备忘录』之 Vim 命令详解

运维人员不仅要熟悉操作系统、服务器、网络等只是&#xff0c;甚至对于开发相关的也要有所了解。很多运维工作者可能一时半会记不住那么多命令、代码、方法、原理或者用法等等。这里我将结合自身工作&#xff0c;持续给大家更新运维工作所需要接触到的知识点&#xff0c;希望大…...

Gcc多版本安装和切换

添加本地source sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update安装 gcc9 和 g9&#xff08;ubuntu18.04&#xff09; sudo apt-get install gcc-9 gcc-9-multilib g-9 g-9-multilib安装 gcc13 和 g13&#xff08;ubuntu22.04&#xff09; sudo …...

【python】OpenCV—Tracking(10.1)

学习来自《Learning OpenCV 3 Computer Vision with Python》Second Edition by Joe Minichino and Joseph Howse 文章目录 检测移动的目标涉及到的 opencv 库cv2.GaussianBlurcv2.absdiffcv2.thresholdcv2.dilatecv2.getStructuringElementcv2.findContourscv2.contourAreacv2…...

计算机网络(复习资料)

1.互联网的两个重要基本特点 连通性和共享性 2.计算机网络由若干节点和连接这些节点的链路组成 3.有多个网络通过路由器相互连接起来,构成一个更大的计算机网络称为互联网 4.网络把许多计算机连接在一起,互联网把许多网络通过一些路由器连接在一起,与网络相连的计算机称为…...

AIGC技术讲解以及应用的落地

简介 近期&#xff0c;火爆的“AI绘画”、图片转AI图&#xff0c;智能聊天软件ChatGPT&#xff0c;引起了人们广泛关注。人工智能潜力再次被证明&#xff0c;而这三个概念均来自同一个领域&#xff1a;AIGC。AIGC到底是什么&#xff1f;为什么如此引人关注&#xff1f;AIGC能产…...

Unity_ShaderGraph示例项目启动

Unity_ShaderGraph示例项目启动 大前提不变:URP模板,Unity2023.1.19使用 Shader Graph - Unity 手册Shader Graph 是一个工具,能够让您直观地构建着色器。您可以在图形框架中创建并连接节点,而不必手写代码。Shader Graph 提供了能反映所作更改的即时反馈,对于不熟悉着色…...

【Eclipse平台】1Eclipse平台总体概览

Eclipse平台总览 欢迎来到【Eclipse平台系列】,本文介绍Eclipse平台的总体概览 文章目录 Eclipse平台总览1. 什么Eclipse开放的架构2. 如何下载Eclipse3. Eclipse的命名规则3. Eclipse的构成3.1 Workbench1. 什么Eclipse Eclipse是一个流行的集成开发环境(Integrated Devel…...

Dijkstra求最短路 I

题目 给定一个n个点m条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c;所有边权均为正值。 请你求出1号点到n号点的最短距离&#xff0c;如果无法从1号点走到n号点&#xff0c;则输出−1。 输入格式&#xff1a; 第一行包含整数n和m。 接下来m行&#xff0c;每…...

复习单向,双向链表,并且实现两种链表的增加和删除功能。

单链表头插 Linklist insert_head(datatype element,Linklist head) {//创建新节点 Linklist screate_node();if(NULLs)return head; s->dataelement;//1,判断链表为空if(NULLhead){heads;}else //链表不为空{s->nexthead;heads;}return head; } 单链表尾插 Linklist …...

【webpack】技巧使用

webpack和TypeScript 安装webpack相关内容安装TS相关内容配置初始化数据初始化运行展示和目录展示报错解决&#xff08;缺失文件配置&#xff09; 安装前端必备神奇lodash测试一下entry配置index.html模板配置修改打包出来的index.html的titleinject注入chunks 属性多页面配置 …...

windows 谷歌浏览器Chrome 怎么禁止更新

1.首先把任务管理器里的谷歌浏览器程序结束&#xff1a; &#xff08;鼠标在任务栏右击&#xff0c;出现任务管理器&#xff09; 2.windowr&#xff0c;输入services.msc 带有Google Update的服务&#xff0c;选择禁用。 3.windowr&#xff0c;输入taskschd.msc 任务计划程序…...

力扣(leetcode)第349题两个数组的交集(Python)

349.两个数组的交集 题目链接&#xff1a;349.两个数组的交集 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,2,1], nums2 [2,2] 输出…...

python Flask 写一个简易的 web 端程序(附demo)

python Flask 写一个简易的 web 端程序 &#xff08;附demo&#xff09; 介绍简单介绍装饰器 app.route("/") 进阶增加接口设置端口 静态网页核心代码完整代码 介绍 Flask 是一个用于构建 Web 应用程序的轻量级 Python Web 框架。它设计简单、易于学习和使用&#x…...

mysql问题

面试官&#xff1a;MySQL中&#xff0c;如何定位慢查询? 候选人&#xff1a; 嗯~&#xff0c;我们当时做压测的时候有的接口非常的慢&#xff0c;接口的响应时间超过了2秒以上&#xff0c;因为我们当时的系统部署了运维的监控系统Skywalking &#xff0c;在展示的报表中可以看…...

iframe通信,window.postMessage父子项目数据通信

父 > 子 父项目 <iframe:src"cockpitUrl"id"cockpitIframe"load"handleLoad" ></iframe>// 向子系统传递数据&#xff08;注意要再iframe的load中注册&#xff0c;保证iframe已经加载完成&#xff0c;这样子项目才能监听到&…...

ES6中新增Array.from()函数的用法详解

目录 Map对象的转换 Set对象的转换 字符串的转换 类数组对象的转换 Array.from可以接受三个参数 ES6为Array增加了from函数用来将其他对象转换成数组。当然&#xff0c;其他对象也是有要求&#xff0c;也不是所有的&#xff0c;可以将两种对象转换成数组。 1、部署了Iter…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

关于uniapp展示PDF的解决方案

在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项&#xff1a; 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库&#xff1a; npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…...

如何把工业通信协议转换成http websocket

1.现状 工业通信协议多数工作在边缘设备上&#xff0c;比如&#xff1a;PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发&#xff0c;当设备上用的是modbus从站时&#xff0c;采集设备数据需要开发modbus主站&#xff1b;当设备上用的是西门子PN协议时&#xf…...