【linux网络编程】| socket套接字 | 实现UDP协议聊天室

        前言:本节内容将带友友们实现一个UDP协议的聊天室。 主要原理是客户端发送数据给服务端。 服务端将数据再转发给所有链接服务端的客户端。 所以, 我们主要就是要实现客户端以及服务端的逻辑代码。 那么, 接下来开始我们的学习吧。

        ps:本节内容建议了解socket套接字的接口的友友们进行观看哦,本节内容中涉及到的接口都不会讲解, 直接就用了。

目录

 整体代码

Udpclient

UdpServer

main(配合UdpServer, UdpServer的入口) 

准备文件

实现步骤

实现服务端客户端的收发消息

Udpserver

Init函数

run函数 

 UdpServer析构

Udpclient

实现客户端之间的聊天功能

Udpserver

Udpclient

运行结果


 整体代码

        先上整体代码:

Udpclient


#include<iostream>
using namespace std;
#include<string>
#include<sys/types.h>
#include"Log.hpp"
#include<sys/socket.h>
#include<pthread.h>
#include<arpa/inet.h>
#include<string.h>
#include<netinet/in.h>
Log lg;class ThreadData
{
public:sockaddr_in server;int sockfd;
};void* recv_message(void* args)
{char buffer[1024];ThreadData* td = static_cast<ThreadData*>(args);    while (true){//接收数据sockaddr_in temp;socklen_t len;string info;ssize_t s = recvfrom(td->sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr*)&temp, &len);if (s < 0){lg(Error, "recv error, error: %d, strerror: %s", errno, strerror(errno));continue;}buffer[s] = 0;info = buffer;cout << info << endl;}}void* send_message(void* args)
{ThreadData* td = static_cast<ThreadData*>(args);string message;while (true){ getline(cin, message);  //获取数据//发送数据sendto(td->sockfd, message.c_str(), message.size(), 0, (sockaddr*)&td->server, sizeof(td->server));}
}int main(int argc, char* argv[])
{if (argc != 3){cout << "Client server" << endl;}//先拿到套接字的参数string serverip = argv[1];uint16_t serverport = stoi(argv[2]);ThreadData td;//创建套接字与打开网卡memset(&td.server, 0, sizeof(td.server));td.server.sin_family = AF_INET;td.server.sin_port = htons(serverport);td.server.sin_addr.s_addr = inet_addr(serverip.c_str());td.sockfd = socket(AF_INET, SOCK_DGRAM, 0); //创建文件描述符, 网卡的文件描述符, 网络传输就是使用网络文件描述符找到对应的文件内的数据if (td.sockfd < 0){lg(Error, "client create sockfd error, errno: %d, strerror: %s", errno, strerror(errno));exit(1);}//创建线程, 然后运行线程, 等待线程pthread_t recv, send;pthread_create(&recv, nullptr, recv_message, &td);pthread_create(&send, nullptr, send_message, &td);pthread_join(recv, nullptr);pthread_join(send, nullptr);close(td.sockfd);return 0;
}

UdpServer

#include<iostream>
using namespace std;
#include<sys/types.h>
#include<string>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<strings.h>
#include"Log.hpp"
#include<functional>
#include<netinet/in.h>
#include<unordered_map>int defaultport = 8080;
string defaultip = "0.0.0.0";using func_t = function<string(string, sockaddr_in&, unordered_map<string, sockaddr_in>&)>; 
Log lg;enum
{SockError = 2,BindError = 3,RecvError = 4,
};class UdpServer
{
public:UdpServer(uint16_t port = defaultport) : port_(port), ip_(defaultip), isrunning_(false){}void Init(){//先创建套接字变量并且完成初始化。 然后就创建网卡文件sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(port_);local.sin_addr.s_addr = inet_addr(ip_.c_str());sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd_ < 0){lg(Fatal, "create sock error, errno: %d, strerror: %s", errno, strerror(errno));exit(SockError);}lg(Info, "create sock success");//绑定if (bind(sockfd_, (sockaddr*)&local, sizeof(local)) < 0) {lg(Fatal, "bind error, errno: %d, strerror: %s", errno, strerror(errno));exit(BindError);}lg(Info, "bind success");}void BroadCast(string message, unordered_map<string, sockaddr_in>& clients){cout << "1 "<< endl;for (auto& e : clients){sendto(sockfd_, message.c_str(), message.size(), 0, (sockaddr*)&e.second, sizeof(e.second));}cout << "2 " << endl;}void run(func_t func){isrunning_ = true;char inbuffer[1024];while (isrunning_){memset(inbuffer, 0, sizeof(inbuffer));sockaddr_in client;socklen_t client_len;memset(&client, 0, sizeof(client));//接收数据的同时监听到客户端的来源ssize_t s = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (sockaddr*)&client, &client_len);if (s < 0) {lg(Waring, "recvfrom error, errno: %d, strerror: %s", errno, strerror(errno));continue;}inbuffer[s] = 0;//处理数据//创建套接字, 用来监听是哪一个客户端string message = inbuffer;message = func(message, client, clients);//处理完成后, 返回发送给客户端BroadCast(message, clients);// sendto(sockfd_, message.c_str(), message.size(), 0, (sockaddr*)&client, sizeof(client));}}~UdpServer(){if (sockfd_ > 0) close(sockfd_);    }
private:int sockfd_;uint16_t port_;string ip_;bool isrunning_;unordered_map<string, sockaddr_in> clients;};

main(配合UdpServer, UdpServer的入口) 


#include"UdpServer.hpp"
#include<memory>string Handler(string message, sockaddr_in& client, unordered_map<string, sockaddr_in>& clients)
{string tmp = inet_ntoa(client.sin_addr) + to_string(client.sin_port);if (!clients.count(tmp)){clients[tmp] = client; cout << "ip " << inet_ntoa(client.sin_addr) << " : port " << client.sin_port << " has add in talk room" << endl;}message = "[" + string(inet_ntoa(client.sin_addr)) + ":" + to_string(client.sin_port) + "]#: " + message; return message;
}int main(int argc, char* argv[])
{if (argc != 2){cout << "has return" << endl;return 1;}//uint16_t serverport = stoi(argv[1]);  unique_ptr<UdpServer> svr(new UdpServer(serverport));//svr->Init();svr->run(Handler);return 0;
}

准备文件

        我们要准备三个文件

  •         Udpclient.cc——用来运行起来客户端
  •         UdpServer.hpp——用来实现服务端的各种接口
  •         main.cc——用来运行起来服务端

        除了这三个主要的文件。 其实博主还准备了两个可以忽略的文件(为了方便)。 一个是博主自己写的日志程序, 用来打印日志。 一个是makefile, 方便编译。 

        如果没有日志程序的话,打印错误信息时直接cout, printf打印即可。 makefile建议带上, 方便编译养成好习惯。

实现步骤

注意, 一步到位是很难的。 所以我们先实现简单的功能, 再实现困难的功能。

        这里简单的功能就是,先让客户端能够将数据发给服务端了, 然后服务端接收到消息后再将数据返回给客户端。

        这里困难的功能就是当多个客户端如何看到互相的信息。然后如何能够一遍发信息,一边收信息。 

实现服务端客户端的收发消息

Udpserver

        实现逻辑:Udpserver.hpp中封装一个类。这个类里面封装一些接口, 然后我们在main函数中创建类对象, 在执行接口操作。

        所以, 先封装一个类, 将要实现的接口以及要用到的变量写上, 实现一个框架:

#include<iostream>
using namespace std;
#include<string>int defaultport = 8080;       //默认的端口号,我们要创建一个默认的端口号
string defaultip = "0.0.0.0"; //在服务器中使用套接字的时候, bind函数不能绑定公网IP, 因为
//服务器的公网IP可能是虚拟的, 注意,IP地址是和网卡挂钩的, 一个网卡只能有一个IP地址。 
//绑定ip地址就是说在绑定网卡,也就是说绑定某个IP地址后就只能监听这一个网卡的消息了。 但是
//有些机器是有很多张网卡的, 所以就有一个默认IP:0.0.0.0, 绑定这个IP就能监听在本机器下面
//所有的网卡的信息。 Log lg;class UdpServer
{
public:UdpServer(uint16_t port = defaultport) : port_(port), ip_(defaultip), isrunning_(false){}void Init(){}void run(func_t func){}~UdpServer(){}
private:int sockfd_;     //服务端的网卡文件的编号uint16_t port_;  //服务器起来后的端口号string ip_;      //服务器起来的时候所在的ip地址bool isrunning_; //服务器是否正在运行};

        下面是main.cpp里面的内容, 直接启动服务端。 

#include"UdpServer.hpp"
#include<memory>int main(int argc, char* argv[])
{if (argc != 2){cout << "has return" << endl;return 1;}//uint16_t serverport = stoi(argv[1]);  unique_ptr<UdpServer> svr(new UdpServer(serverport));//svr->Init();svr->run();return 0;
}

Init函数

        Udpserver里面的Init函数, 这个函数用来绑定服务端的套接字的。 什么是绑定? 博主目前的理解就是将我们运行的服务端这个程序能够和网卡建立起关系。         

        这个关系中, 关系的两端是我们运行的服务端程序和socket网卡文件(网卡文件就代表了网卡)。关系的纽带是ip地址和端口号。 利用ip地址和端口号来将我们的服务端程序绑定给网卡, 这个时候因为网卡的工作性质, 其他的进程都不能再绑定网卡了, 直到我们的服务端退出。 

    void Init(){//先创建套接字变量并且完成初始化。 然后就创建网卡文件sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(port_);local.sin_addr.s_addr = inet_addr(ip_.c_str());sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd_ < 0){lg(Fatal, "create sock error, errno: %d, strerror: %s", errno, strerror(errno));exit(SockError);}lg(Info, "create sock success");//绑定if (bind(sockfd_, (sockaddr*)&local, sizeof(local)) < 0) {lg(Fatal, "bind error, errno: %d, strerror: %s", errno, strerror(errno));exit(BindError);}lg(Info, "bind success");}

run函数 

        我们这里思考一个问题, 我们要实现的其实是服务端与客户端之间收发消息。 所以, 我们就要客户端先发, 然后服务端收消息。 

        然后! 服务端收到消息将消息 处理一下 再将消息发回客户端。

        所以,这个过程中服务端有三个主要的动作, 一个是收,一个是处理, 一个是发。         

        然后我们的处理怎么处理, 我们可以将处理动作暴露出去,  交给main.cpp来决定。 ——利用回调函数, main.cpp中将要执行的动作作为函数传给run函数。 

如下为接口:

    //这里的func_t是一个回调函数的类型。 什么类型, 使用包装器包装的!注意//包含头文件functionalusing func_t = function<string(string)>; void run(func_t func){isrunning_ = true;char inbuffer[1024];while (isrunning_){memset(inbuffer, 0, sizeof(inbuffer));sockaddr_in client;socklen_t client_len;memset(&client, 0, sizeof(client));//接收数据的同时监听到客户端的来源ssize_t s = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (sockaddr*)&client, &client_len);if (s < 0) {lg(Waring, "recvfrom error, errno: %d, strerror: %s", errno, strerror(errno));continue;}inbuffer[s] = 0;//处理数据//创建套接字, 用来监听是哪一个客户端string message = inbuffer;message = func(message);//这里的处理使用一个外部的接口//处理完成后, 返回发送给客户端sendto(sockfd_, message.c_str(), message.size(), 0, (sockaddr*)&client, sizeof(client));}}

 UdpServer析构

析构函数不解释

    ~UdpServer(){if (sockfd_ > 0) close(sockfd_);    }

Udpclient

        客户端就是给对应的服务端发送数据。 数据被服务端处理后接收即可:

#include<iostream>
#include<cstdlib>
#include<unistd.h>
using namespace std;
#include<sys/types.h>
#include<strings.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<cstring>
#include<string>//./udpclient serverip serverport 
int main(int argc, char* argv[])
{if (argc != 3){cout << "has return" << endl;return 1;}//string serverip = argv[1];uint16_t serverprot = stoi(argv[2]);//创建套接字struct sockaddr_in server;bzero(&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverprot);server.sin_addr.s_addr = inet_addr(serverip.c_str());socklen_t serlen = sizeof(server);int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){cout << "socker error" << endl; return 1;}string message;char buffer[1024];while(true){   cout << "please Enter@:" << endl;getline(cin, message);  //发送数据sendto(sockfd, message.c_str(), message.size(), 0,  (struct sockaddr*)&server, serlen);cout << "yes" << endl;//接收数据sockaddr_in temp;socklen_t socklen;ssize_t sz = recvfrom(sockfd, (void*)buffer, sizeof(buffer) - 1, 0, (sockaddr*)&temp, &socklen); //sockfd其实就是网卡的pidif(sz > 0){buffer[sz] = 0;cout << buffer << endl;}}close(sockfd);return 0;
}

实现客户端之间的聊天功能

Udpserver

        实现客户端之间的聊天可是说是在上面的代码中改两个地方。 一个是创建一个哈希表存储有多少客户端连接了服务端。 然后以后发消息就直接便利整个哈希表, 然后将数据发给每一个客户端。 如下:

#include<iostream>
using namespace std;
#include<sys/types.h>
#include<string>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<strings.h>
#include"Log.hpp"
#include<functional>
#include<netinet/in.h>
#include<unordered_map>int defaultport = 8080;
string defaultip = "0.0.0.0";//包装类要进行修改一下
using func_t = function<string(string, sockaddr_in&, unordered_map<string, sockaddr_in>&)>; Log lg;enum
{SockError = 2,BindError = 3,RecvError = 4,
};class UdpServer
{
public:UdpServer(uint16_t port = defaultport) : port_(port), ip_(defaultip), isrunning_(false){}//Init不变void Init(){//先创建套接字变量并且完成初始化。 然后就创建网卡文件sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(port_);local.sin_addr.s_addr = inet_addr(ip_.c_str());sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd_ < 0){lg(Fatal, "create sock error, errno: %d, strerror: %s", errno, strerror(errno));exit(SockError);}lg(Info, "create sock success");//绑定if (bind(sockfd_, (sockaddr*)&local, sizeof(local)) < 0) {lg(Fatal, "bind error, errno: %d, strerror: %s", errno, strerror(errno));exit(BindError);}lg(Info, "bind success");}//遍历哈希表,将数据分发给所有的客户端void BroadCast(string message, unordered_map<string, sockaddr_in>& clients){cout << "1 "<< endl;for (auto& e : clients){sendto(sockfd_, message.c_str(), message.size(), 0, (sockaddr*)&e.second, sizeof(e.second));}cout << "2 " << endl;}void run(func_t func){isrunning_ = true;char inbuffer[1024];while (isrunning_){memset(inbuffer, 0, sizeof(inbuffer));sockaddr_in client;socklen_t client_len;memset(&client, 0, sizeof(client));//接收数据的同时监听到客户端的来源ssize_t s = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (sockaddr*)&client, &client_len);if (s < 0) {lg(Waring, "recvfrom error, errno: %d, strerror: %s", errno, strerror(errno));continue;}inbuffer[s] = 0;//处理数据//创建套接字, 用来监听是哪一个客户端string message = inbuffer;message = func(message, client, clients);//这里的处理使用一个外部的接口//处理完成后, 返回发送给客户端BroadCast(message, clients);}}~UdpServer(){if (sockfd_ > 0) close(sockfd_);    }
private:int sockfd_;uint16_t port_;string ip_;bool isrunning_;unordered_map<string, sockaddr_in> clients; //添加哈希表};

#include"UdpServer.hpp"
#include<memory>//main.cc主要修改就是Handler函数, 我们要通过client里面的ip地址和端口号作为key,client作为value,然后放入哈希表。 同时将message处理一下,方便我们观看结果。 
string Handler(string message, sockaddr_in& client, unordered_map<string, sockaddr_in>& clients)
{string tmp = inet_ntoa(client.sin_addr) + to_string(client.sin_port);if (!clients.count(tmp)){clients[tmp] = client; cout << "ip " << inet_ntoa(client.sin_addr) << " : port " << client.sin_port << " has add in talk room" << endl;}message = "[" + string(inet_ntoa(client.sin_addr)) + ":" + to_string(client.sin_port) + "]#: " + message; return message;
}// int main(int argc, char* argv[])
{if (argc != 2){cout << "has return" << endl;return 1;}//uint16_t serverport = stoi(argv[1]);  unique_ptr<UdpServer> svr(new UdpServer(serverport));//svr->Init();svr->run(Handler);return 0;
}

Udpclient

#include<iostream>
using namespace std;
#include<string>
#include<sys/types.h>
#include"Log.hpp"
#include<sys/socket.h>
#include<pthread.h>
#include<arpa/inet.h>
#include<string.h>
#include<netinet/in.h>
Log lg;class ThreadData
{
public:sockaddr_in server;int sockfd;
};//数据接收函数
void* recv_message(void* args)
{char buffer[1024];ThreadData* td = static_cast<ThreadData*>(args);    while (true){//接收数据sockaddr_in temp;socklen_t len;string info;ssize_t s = recvfrom(td->sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr*)&temp, &len);if (s < 0){lg(Error, "recv error, error: %d, strerror: %s", errno, strerror(errno));continue;}buffer[s] = 0;info = buffer;cout << info << endl;}}//数据发送函数
void* send_message(void* args)
{ThreadData* td = static_cast<ThreadData*>(args);string message;while (true){  getline(cin, message);  //获取数据//发送数据sendto(td->sockfd, message.c_str(), message.size(), 0, (sockaddr*)&td->server, sizeof(td->server));}
}int main(int argc, char* argv[])
{if (argc != 3){cout << "Client server" << endl;}//先拿到套接字的参数string serverip = argv[1];uint16_t serverport = stoi(argv[2]);ThreadData td;//创建套接字与打开网卡memset(&td.server, 0, sizeof(td.server));td.server.sin_family = AF_INET;td.server.sin_port = htons(serverport);td.server.sin_addr.s_addr = inet_addr(serverip.c_str());td.sockfd = socket(AF_INET, SOCK_DGRAM, 0); //创建文件描述符, 网卡的文件描述符, 网络传输就是使用网络文件描述符找到对应的文件内的数据if (td.sockfd < 0){lg(Error, "client create sockfd error, errno: %d, strerror: %s", errno, strerror(errno));exit(1);}//创建线程, 然后运行线程, 等待线程pthread_t recv, send;pthread_create(&recv, nullptr, recv_message, &td);pthread_create(&send, nullptr, send_message, &td);pthread_join(recv, nullptr);pthread_join(send, nullptr);close(td.sockfd);return 0;
}

运行结果

最后就是运行结果, 运行结果就是下图了, 我们已经能够成功的进行两个客户端之间的远程交流

 ——————以上就是本节全部内容哦, 如果对友友们有帮助的话可以关注博主, 方便学习更多知识哦!!! 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TIFS-2024 FIRe2:细粒度表示和重组在换衣行人重识别中的应用

总体结论 本文提出了一种新的细粒度表示与重构&#xff08;FIRe2&#xff09;框架&#xff0c;用于解决布变人重识别问题。通过细粒度特征挖掘和属性重构&#xff0c;FIRe2在不依赖任何辅助信息的情况下&#xff0c;实现了最先进的性能。该方法在多个基准数据集上取得了显著的…

一款专业获取 iOS 设备的 UDID 工具|一键获取iPhone iPad设备的 UDID

什么是UDID&#xff1f; UDID&#xff0c;是iOS设备的一个唯一识别码&#xff0c;每台iOS设备都有一个独一无二的编码&#xff0c;这个编码&#xff0c;我们称之为识别码&#xff0c;也叫做UDID&#xff08; Unique Device Identifier&#xff09; 扫描后系统提示输入密码&am…

HTML--浮动布局练习

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>/* 整个浏览器页…

ES6 变量的解构赋值

数组的解构赋值 对象的解构赋值 字符串的解构赋值

利用游戏引擎的优势

大家好&#xff0c;我是小蜗牛。 在当今快速发展的游戏产业中&#xff0c;选择合适的游戏引擎对开发者来说至关重要。Cocos Creator作为一款功能强大且灵活的游戏引擎&#xff0c;为开发者提供了丰富的工具和资源&#xff0c;使他们能够高效地开发出优秀的游戏。本文将探讨如何…

Python+Selenium+Pytest+POM自动化测试框架封装(完整版)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、测试框架简介 1&#xff09;测试框架的优点 代码复用率高&#xff0c;如果不使用框架的话&#xff0c;代码会显得很冗余。可以组装日志、报告、邮件等一些高…

【鸿蒙HarmonyOS实战:通过华为应用市场上架测试版App实现HBuilder X打包的UniApp项目的app转hap教程(邀请码)方式教程详解】

鸿蒙HarmonyOS实战&#xff1a;通过华为应用市场上架测试版App实现HBuilder X打包的UniApp项目的app转hap教程&#xff08;邀请码&#xff09;方式详解 在使用uniapp打包的鸿蒙项目的过程中&#xff0c;由于生成的是app文件&#xff0c;而hdc传给鸿蒙HarmonyOS系统需要的是hap文…

【Apache Zookeeper】

一、简介 1、场景 如何让⼀个应⽤中多个独⽴的程序协同⼯作是⼀件⾮常困难的事情。开发这样的应⽤&#xff0c;很容易让很多开发⼈员陷⼊如何使多个程序协同⼯作的逻辑中&#xff0c;最后导致没有时间更好地思考和实现他们⾃⼰的应⽤程序逻辑&#xff1b;又或者开发⼈员对协同…

名词(术语)了解--SSR/CSR

名词&#xff08;术语&#xff09;了解–SSR/CSR 什么是服务器端渲染(SSR)? 服务器端渲染是指由服务器生成完整的 HTML 页面&#xff0c;然后发送给客户端的过程。 这与客户端渲染&#xff08;CSR&#xff09;形成对比&#xff0c;后者主要依赖浏览器端的 JavaScript 来渲染…

有趣智力题(非编程题)

目录 赛马烧香问题 赛马 题目描述: 一共有36匹马 6个跑道 在没有计时器的情况下 请问: 最少进行多少次赛马 可以确定前三名? 答案:8次 图解思路: 注意下图写错了 注释没写错 图画错了 正确的是下图 烧香问题 题目描述: 有两根香 材质不均匀 但是每一根香 烧完都需要1h 请利用…

学习threejs,使用粒子实现下雪特效

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.Points简介1.11 ☘️…

Golang | Leetcode Golang题解之第517题超级洗衣机

题目&#xff1a; 题解&#xff1a; func findMinMoves(machines []int) (ans int) {tot : 0for _, v : range machines {tot v}n : len(machines)if tot%n > 0 {return -1}avg : tot / nsum : 0for _, num : range machines {num - avgsum numans max(ans, max(abs(sum…

算法练习:209. 长度最小的子数组

题目链接&#xff1a;209. 长度最小的子数组。 这里ans来统计最小长度&#xff0c;所以初始值设置为INT_MAX.最后如果ans结果还是INT_MAX时&#xff0c;说明无此数组。 class Solution { public:int minSubArrayLen(int target, vector<int>& nums) {if (nums.size(…

WPF+MVVM案例实战(十一)- 环形进度条实现

文章目录 1、运行效果2、功能实现1、文件创建与代码实现2、角度转换器实现3、命名空间引用 3、源代码下载 1、运行效果 2、功能实现 1、文件创建与代码实现 打开 Wpf_Examples 项目&#xff0c;在Views 文件夹下创建 CircularProgressBar.xaml 窗体文件。 CircularProgressBa…

《贪婪算法实战:寻找最短无序连续子数组的深度解析与实现》

🚀 博主介绍:大家好,我是无休居士!一枚任职于一线Top3互联网大厂的Java开发工程师! 🚀 🌟 在这里,你将找到通往Java技术大门的钥匙。作为一个爱敲代码技术人,我不仅热衷于探索一些框架源码和算法技巧奥秘,还乐于分享这些宝贵的知识和经验。 💡 无论你是刚刚踏…

堆的基本概念和插入删除方法的介绍

优先级队列的介绍&#xff1a; 1.1优先级队列&#xff1a;优先级队列是一种特殊的队列数据结构&#xff0c;每个元素都有一个与之关联的优先级&#xff0c;与普通队列不同&#xff0c;优先级队列中的元素是按照优先级顺序进行处理的&#xff0c;而不是简单的插入。 特点&…

雷军:对“雷军语音包”感到不适,希望停止使用

对于社交媒体上频繁出现的“雷军AI语音包”&#xff0c;雷军发声回应。10月29日&#xff0c;雷军发布视频表示&#xff1a;“最近两年AI特别火&#xff0c;技术进步特别得快&#xff0c;前段时间我在刷抖音的时候&#xff0c;经常看到很多人在玩‘雷军AI’&#xff0c;就是雷军…

分布式光伏是什么意思?如何高效管理?

分布式光伏系统是指在用户现场或靠近用电现场配置较小的光伏发电供电系统&#xff0c;以满足特定用户的需求。根据通知&#xff0c;分布式光伏系统主要有以下几类定义&#xff1a; 10kV以下电压等级接入&#xff0c;且单个并网点总装机容量不超过6MW的分布式电源&#xff1a;这…

项目1 yolov5鱼苗检测计数

yolov5鱼苗检测 1. yolov5鱼苗检测1.1. 环境配置1.2 Predict1.3 Validate1.4 Train1.5 生成 ONNX 2 代码解析2.1 模型2.2 数据集2.3 损失函数2.4 训练2.5 预测 之前做的项目&#xff0c;再回顾一下 环境&#xff1a;GPU1卡&#xff0c;CPU4核&#xff0c;每显卡12GB&#xff0c…

智能文档处理平台:免费体验智能化医疗信息提取

前提&#xff1a;医疗行业信息碎片化问题普遍&#xff0c;手工数据录入效率低且易错&#xff0c;导致数据管理难度大。本系统可帮助医疗机构在信息管理上迈向智能化&#xff0c;优化流程并提升效率。 系统概述&#xff1a; 思通数科推出的智能文档处理系统&#xff0c;专为解…