牛客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 山西

相关推荐

WebSocket是一种在Web应用程序中实现实时双向通信的技术。它提供了一种持久连接,允许服务器与客户端之间进行双向数据传输。与传统的HTTP请求/响应模型不同,WebSocket允许服务器主动向客户端发送消息,而不需要客户端发起请求。要在Web应用程序中使用WebSocket进行实时通信,需要执行以下步骤:https://www.nowcoder.com/issue/tutorial?zhuanlanId=Mg58Em&amp;uuid=b48bebe08e474db8b80b853b12bafd48创建一个WebSocket对象:使用JavaScript的WebSocket构造函数创建一个WebSocket对象,指定要连接的服务器URL。例如:var&nbsp;socket&nbsp;=&nbsp;new&nbsp;WebSocket(&quot;ws://example.com/socket-server&quot;);监听WebSocket事件:使用WebSocket对象的事件监听器来处理WebSocket的各种事件,例如onopen、onmessage、onclose和onerror。这些事件将在WebSocket状态变化、接收到消息、关闭连接或发生错误时被触发。建立连接:一旦创建了WebSocket对象,通过调用其open()方法建立与服务器的WebSocket连接。当连接建立成功时,onopen事件将被触发。发送和接收消息:使用WebSocket对象的send()方法向服务器发送消息,消息可以是字符串或其他数据类型。服务器接收到消息后,可以使用WebSocket对象的onmessage事件来处理。关闭连接:当需要终止WebSocket连接时,可以调用WebSocket对象的close()方法。服务器会收到一个关闭请求,如果确定关闭连接,会发送一个关闭信号给客户端并触发onclose事件。通过使用WebSocket,Web应用程序可以实现实时的双向通信,适用于聊天应用、实时通知、实时更新和协同编辑等场景。#ai智能作图#
点赞 评论 收藏
分享
评论
1
1
分享
牛客网
牛客企业服务