牛客Rust社区(web server Chapter 1)

找了很久牛客上面也有很多rust爱好者,但是Rust就没有类似Java求职、C++项目等圈子广场,希望官方可以提供一个Rust爱好交流圈子啥的。

C++项目者应该做过最多的就是web server服务器了,用Rust简单复现一个.

前置依赖:

toml 文件

tracing = "0.1.37"
tracing-subscriber = "0.3.17"
// 日志文件

第一步先注册一下全局日志,我不太喜欢println的方式打印,感觉那样太简陋且也没有可读性。

// 注册日志
tracing_subscriber::registry()
   .with(fmt::layer())
   .init();

然后是监听端口:127.0.0.1:8888

let listener = TcpListener::bind("127.0.0.1:8888").unwrap();
listener.incoming().map(Result::unwrap).for_each(handle_connection);
// handle_connection 是后面具体请求处理的方法,这儿先过滤,后面会讲

这样子就可以监听一个请求了,可以直接通过浏览器进行访问,但是我们怎么判断一个请求是否正确呢?这儿就得考虑http请求格式了。

可以通过这种方式在handle_connection方法中打印http_request看看格式,上面我写的方式是函数式编程,可能没怎么了解过rust的同学看起来估计可读性不高,我简单解释下:

  1. listener.incoming() 返回一个流(stream)的迭代器,该迭代器代表监听器接收到的传入连接。
  2. map(Result::unwrap) 对流中的每个元素执行 Result::unwrap 操作,将 Ok(T) 转换为对应的 T 值,忽略 Err 的情况。这是因为 listener.incoming() 返回的是一个 Result<TcpStream, Error> 类型,使用 Result::unwrap 可以提取出成功的 TcpStream 值。
  3. for_each(handle_connection) 对经过映射处理后的每个流应用 handle_connection 函数。for_each 方法接受一个闭包作为参数,并对流进行迭代并执行闭包中定义的操作。在这里,handle_connection 函数被应用于每个流上,实现对每个连接的处理。

故而上面其实最终传入handle_connection方法的都是一个TcpStream值。所以我们可以这么打印。

let buf_reader = BufReader::new(&mut stream);
let http_request: Vec<_> = buf_reader
   .lines()
   .map(|result| result.unwrap())
   .take_while(|line| !line.is_empty())
   .collect();

 tracing::info!("Request: {:#?}", http_request);

可以看到格式是这样的:

这儿我们判断比较简单,通过request的第一个值判断是否走http请求

let buf_reader = BufReader::new(&mut stream);
let request_line = buf_reader.lines().next().unwrap().unwrap();

let (status_line, filename) = match request_line.as_str() {
    "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"),
    _ => ("HTTP/1.1 404 NOT FOUND", "404.html"),
};
let contents = fs::read_to_string(filename).unwrap();
let length = contents.len();
let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");
stream.write_all(response.as_bytes()).unwrap();

这儿的hello.html和 `404.html` 是我个人基于根目录创建的文件,这样子就可以给用户基本的展示了,这儿其实非常简单,就和用springboot写一个hello world的controller一样,当前是单线程的,肯定会出现阻塞的情况,下个文章准备写一个线程池来实现多线程不阻塞工作。

#Rust##Rust社区##悬赏#
全部评论
对了,文中的handle_connection方法定义是这样的:fn handle_connection(mut stream: TcpStream) {...} 中间就是具体的stream的操作,比如在文中打印http_request
点赞 回复 分享
发布于 2023-07-29 22:51 北京
我就是双飞本夸材料跨专业进计算机的。 老哥这是你去年一月的一个评论。 请问你跨考后悔吗,老实说小弟计算机专业有点想跨考材料了
点赞 回复 分享
发布于 2023-08-01 06:37 山西

相关推荐

头像
11-21 11:39
四川大学 Java
是红鸢啊:忘了还没结束,还有字节的5k 违约金
点赞 评论 收藏
分享
joe2333:怀念以前大家拿华为当保底的日子
点赞 评论 收藏
分享
1 1 评论
分享
牛客网
牛客企业服务