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

郑州建网站需要多少钱平面广告设计用什么软件

郑州建网站需要多少钱,平面广告设计用什么软件,网站平台建设十大公司,苏州艺术家网站建设wmproxy wmproxy是由Rust编写#xff0c;已实现http/https代理#xff0c;socks5代理#xff0c; 反向代理#xff0c;静态文件服务器#xff0c;内网穿透#xff0c;配置热更新等#xff0c; 后续将实现websocket代理等#xff0c;同时会将实现过程分享出来#xff…wmproxy wmproxy是由Rust编写已实现http/https代理socks5代理 反向代理静态文件服务器内网穿透配置热更新等 后续将实现websocket代理等同时会将实现过程分享出来 感兴趣的可以一起造个轮子法 项目地址 gite: https://gitee.com/tickbh/wmproxy github: https://github.com/tickbh/wmproxy 日志功能 为了更容易理解程序中发生的情况我们可能想要添加一些日志语句。通常在编写应用程序时这很容易。「在某种程度上日志记录与使用 println! 相同只是你可以指定消息的重要性」。 在rust中定义的日志级别有5种分别为error、warn、info、debug 和 trace 定义日志的级别是表示只关系这级别的日志及更高级别的日志: 定义log则包含所有的级别 定义warn则只会显示error或者warn的消息 要向应用程序添加日志记录你需要两样东西 log craterust官方指定的日志级别库一个实际将日志输出写到有用位置的适配器 当下我们选用的是流行的根据环境变量指定的适配器env_logger它会根据环境变量中配置的值日志等级或者只开启指定的库等功能或者不同的库分配不同的等级等。 在Linux或者MacOs上开启功能 env RUST_LOGdebug cargo run 在Windows PowerShell上开启功能 $env:RUST_LOGdebug cargo run在Windows CMD上开启功能 set RUST_LOGdebug cargo run如果我们指定库等级可以设置 RUST_LOGinfo,wenmengwarn,webparsewarn这样就可以减少第三方库打日志给程序带来的干扰 需要在Cargo.toml中引用 [dependencies] log 0.4.20 env_logger 0.10.0以下是示意代码 use log::{info, warn}; fn main() {env_logger::init();info!(欢迎使用软件wmproxy);warn!(现在已经成功启动); }用println!将会直接输出到stdout当日志数据多的时候无法进行关闭做为第三方库就不能干扰引用库的正常看日志所以这只能调试的时候使用或者少量的关键地方使用。 多个TcpListener的Accept 因为当前支持多个端口绑定或者配置没有配置存在None的情况我们需要同时在一个线程中await所有的TcpListener。 在这里我们先用的是tokio::select!对多个TcpListener同时进行await。 如果此时我们没有绑定proxy的绑定地址此时listener为None但我们需要进行判断才知道他是否为None如果我们用以下写法 use tokio::net::TcpListener; use std::io;#[tokio::main] async fn main() - io::Result() {let mut listener: OptionTcpListener None;tokio::select! {// 加了if条件判断是否有值Ok((conn, addr)) listener.as_mut().unwrap().accept(), if listener.is_some() {println!(accept addr {:?}, addr);}}Ok(()) }此时我们试运行依然报以下错误 thread main panicked at called Option::unwrap() on a None value, examples/udp.rs:9:46也就是即使加了if条件我们也正确的执行我们的操作因为tokio::select的每个分支必须返回Fut此时如果为None就不能返回Fut违反了该函数的定义那么我们做以下封装 async fn tcp_listen_work(listen: OptionTcpListener) - Option(TcpStream, SocketAddr) {if listen.is_some() {match listen.as_ref().unwrap().accept().await {Ok((tcp, addr)) Some((tcp, addr)),Err(_e) None,}} else {// 如果为None的时候就永远返回Poll::Pendinglet pend std::future::pending();let () pend.await;None} }如果为None的话将其返回Poll::Pending则该分支await的时候永远不会等到结果。 那么最终的的代码示意如下 #[tokio::main] async fn main() - io::Result() {let listener: OptionTcpListener TcpListener::bind(127.0.0.1:8090).await.ok();tokio::select! {Some((conn, addr)) tcp_listen_work(listener) {println!(accept addr {:?}, addr);}}Ok(()) }另一种在反向代理的时候因为server的数量是不定的所以监听的TcpListener也是不定的此时我们用VecTcpListener来做表示那么此时我们如何通过tokio::select来一次性await所有的accept呢 此时我们借助futures库中的select_all来监听但是select_all又不允许空的Vec因为他要返回一个Fut空的无法返回一个Fut所以此时我们也要对其进行封装 async fn multi_tcp_listen_work(listens: mut VecTcpListener) - (io::Result(TcpStream, SocketAddr), usize) {if !listens.is_empty() {let (conn, index, _) select_all(listens.iter_mut().map(|listener| listener.accept().boxed())).await;(conn, index)} else {let pend std::future::pending();let () pend.await;unreachable!()} }此时监听从8091-8099我们的最终代码 #[tokio::main] async fn main() - io::Result() {let listener: OptionTcpListener TcpListener::bind(127.0.0.1:8090).await.ok();let mut listeners vec![];for i in 8091..8099 {listeners.push(TcpListener::bind(format!(127.0.0.1:{}, i)).await?);}tokio::select! {Some((conn, addr)) tcp_listen_work(listener) {println!(accept addr {:?}, addr);}(result, index) multi_tcp_listen_work(mut listeners) {println!(index receiver {:?}, index)}}Ok(()) }如果此时我们用 telnet 127.0.0.1 8098那么我们就可以看到输出 index receiver 7表示代码已正确的执行。 Rust中数据在多个线程中的共享 Rust中每个对象的所有权都仅只能有一个对象拥有那么我们数据在在多个地方共享的时候可以怎么办呢 在单线程中我们可以用use std::rc::Rc; Rc的特点 单线程的引用计数不可变引用非线程安全即仅能在单线程中使用 Rc引用计数中还有一个弱引用称为Weak弱引用表示持有对象的一个指针但是不添加引用计数也不会影响数据删除不保证一定能取得到数据。 因为其不能修改数据所以也常用RefCell做配合来做引用计数的修改。 以下是一个父类子类用弱引用计数实现的方案 use std::rc::Rc; use std::rc::Weak; use std::cell::RefCell;/// 父类拥有者 struct Owner {name: String,gadgets: RefCellVecWeakGadget, }/// 子类对象 struct Gadget {id: i32,owner: RcOwner, }fn main() {let gadget_owner: RcOwner Rc::new(Owner {name: wmproxy.to_string(),gadgets: RefCell::new(vec![]),});// 生成两个小工具let gadget1 Rc::new(Gadget {id: 1,owner: Rc::clone(gadget_owner),});let gadget2 Rc::new(Gadget {id: 2,owner: Rc::clone(gadget_owner),});{let mut gadgets gadget_owner.gadgets.borrow_mut();gadgets.push(Rc::downgrade(gadget1));gadgets.push(Rc::downgrade(gadget2));}for gadget_weak in gadget_owner.gadgets.borrow().iter() {let gadget gadget_weak.upgrade().unwrap();println!(小工具 {} 的拥有者{}, gadget.id, gadget.owner.name);} }因为其并未实现Send函数所以无法在多线程种传递。在多线程中我们需要用Arc但是在Arc获取可变对象的时候有限制必须他是唯一引用的时候才能修改。 use std::sync::Arc; fn main() {let mut x Arc::new(3);*Arc::get_mut(mut x).unwrap() 4;assert_eq!(*x, 4);let _y Arc::clone(x);assert!(Arc::get_mut(mut x).is_none()); }所以我们在多线程中的引用需要修改的时候通常会用Atomic或者Mutex来做数据的写入的唯一性。 #![allow(unused)] fn main() {use std::sync::{Arc, Mutex};use std::thread;use std::sync::mpsc::channel;const N: usize 10;let data Arc::new(Mutex::new(0));let (tx, rx) channel();for _ in 0..N {let (data, tx) (Arc::clone(data), tx.clone());thread::spawn(move || {// 共享数据data保证在线程中只会同时有一个对象拥有修改权限也相当于拥有所有权10个线程每个线程1最终结果必须等于10let mut data data.lock().unwrap();*data 1;if *data N {tx.send(()).unwrap();}});}rx.recv().unwrap();assert!(*data.lock().unwrap() 10); }结语 以上是三种编写Rust中常碰见的情况也是在此项目中应用解决过的方案在了解原理的情况下解决问题可以有不同的思路。理解了原理你就知道他设计的初衷更好的帮助你学习相关的Rust知识。
http://www.zqtcl.cn/news/280107/

相关文章:

  • 桂城网站制作公司wordpress 导航网站
  • 一个公司做网站需要注意什么条件网站备案 登陆
  • 百度网站介绍显示图片装修公司一般多少钱一平方
  • 网站销售如何做业绩我找伟宏篷布我做的事ko家的网站
  • 建立网站有哪些步骤?jsp网站开发详细教程
  • 网站怎么做直播功能旅游做攻略用什么网站
  • 企业外贸营销型网站如何写好软文推广
  • 免费建站的网址个人网站建设程序设计
  • 淘宝网站建设违规吗上海大公司
  • 大淘客怎么自己做网站自己开网站能赚钱吗
  • 大型门户网站开发北京网站建设管庄
  • 大连建设工程网站网站建设组织管理怎么写
  • wordpress英文站注册域名需要注意什么
  • 营销型网站的建设重点是什么深圳logo设计公司排名
  • 做网站的用什么软件呢网站排名优化服务公司
  • 网站开发完整视频网站集约化建设较好的城市
  • 网站建设和平面设计应用网站如何做
  • 自己做网站需要多少费用asa8.4 做网站映射
  • 商业网站 模板黑龙江省建设厅安全员考试
  • 网站新备案不能访问室内装修网站模板
  • 工程师报考网站wordpress设置视频图片不显示图片
  • 徐州网站建设公司排名成都住建平台
  • 用来备案企业网站国外免费外贸网站
  • 网页背景做的比较好的网站做一个企业网站价格
  • 免费制图网站县级门户网站建设的报告
  • 北京网站建设网怎么用手机做一个网站
  • 网站建设管理办法关于公司门户网站建设的议案
  • 网站开发入职转正申请书体验好的网站
  • 在线精品课程网站开发网站备案号怎么修改
  • 网站建设 风险百度热搜的含义