logo

分享之前发帖说走到了瓶颈,最近上手rust,正好写个http服务器来练练手

头像
文翼
30阅读0评论3 个月前

最近在学习rust,大概看了看基础语法过后,写了几个小demo,感觉不是很过瘾。这时发现手册上有tcp的封装,自己做了好几年php,还从来没有自己实现过http的接收和返回,于是动手整了个demo。往这里发一发自己的写法,主要是学习rust语言的语法,请大神不要笑我就行。

大概看了下http的协议内容,主要是文件请求方法的,请求头和相应头的定义,标准化请求和相应内容。这些先全部抛开,整一个能够正常接受到请求并且能够成功返回到例子,作为第一步学习的目的就到了。
所以第一步就是从tcp请求中获取到请求内容。
首先在main函数中定义tcp监听器,申明ip和端口,然后用for in 获取每一个请求,然后用其他函数来处理

let ip = "127.0.0.1:8080"; //监听ip和端口
let listener = TcpListener::bind(ip).expect("没能创建监听");
info!("服务器正在监听 [http://{}]", ip);
for stream in listener.incoming() {
    match stream {
        Ok(stream) => match handle_connection(stream) {
            Ok(_) => (),
            Err(e) => error!("链接处理错误 {}", e),
          },
        Err(e) => error!("链接错误: {}", e),
      }
}

然后申明一块缓存读取请求的内容,为什么要申明缓存呢,明明可以直接放过去,主要是想到一个get请求的url最大可能会有2k,这里也是限制一下。然后将缓存的这个数组转换成字符串,接着下一步。

let mut buffer = [0; 512];
let request = String::from_utf8_lossy(&buffer[..]);

讲真rest这语言的变量是真的要求严谨,写惯了php真的不习惯。尤其是字符串操作,简直复杂。
从客户端传到服务器的内容一半是 method url http版本 .......后面跟请求头,这次只是先写个简单能处理get请求的就行,像post,put,patch,delete,option这些之后再说。
go on
下一步就是解析请求 既然只搞get,这一步就很简单,用空格把字符拆成迭代器就行。然后就跟着next(),就能依次获取到 method,url,和http版本。

let mut parts = request.split_ascii_whitespace();

接着通过url定位获取文件地址,用fs获取文件内容,然后拼接相应头,往会丢就行。

let content = fs::read_to_string(&request.file_path).unwrap();
let response = format!("HTTP/1.1 200 OK \\r\\n\\r\\n{}", content);

这里有个小小的地方,就是文件不存在怎么办。先默认写一个404.html,然后只要文件不存在就返回这个,再加上一个404的状态码。

if !Path::new(&file_path).exists() {
let content = fs::read_to_string("404.html").unwrap();
}

let response = format!("HTTP/1.1 404 Not Found \\r\\n\\r\\n{}", content);

ok,这次就先写到这里。后续还有很多内容,边学边写算了,先插个眼。
还有:

  • 其他请求方法
  • 其他异常返回
  • 多进程处理请求
    ......
分享主题:
经历/经验其它
城市:
成都
加载中…
精选评论
暂无数据

暂无数据