HTTP服务器基础的监听和响应
This commit is contained in:
parent
4bebc4d45e
commit
0597ace088
165
c/test/main.c
165
c/test/main.c
@ -1,164 +1,15 @@
|
||||
//头文件
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <conio.h>
|
||||
#include <time.h>
|
||||
#include<stdio.h>
|
||||
#include<time.h>
|
||||
#include<windows.h>
|
||||
#include<stdlib.h>
|
||||
|
||||
//自定义头文件
|
||||
#include "founction_statement_page.h"//界面
|
||||
#include "function_statement_effect.h"//功能
|
||||
#define aa 2
|
||||
|
||||
//初始化全局变量
|
||||
bool pick_revision = true;//初始化文件是否修改
|
||||
bool pick_view_mode = false;//视图模式
|
||||
unsigned int Total = 0;//初始化学生总数
|
||||
void main(){
|
||||
int a=1,b=2;
|
||||
if(a==aa-1||b==2){
|
||||
|
||||
static struct Snake
|
||||
{
|
||||
//0为y,1为x
|
||||
int head[2];
|
||||
int body[2];
|
||||
int tail[2];
|
||||
};
|
||||
|
||||
static struct Snake snake ;
|
||||
|
||||
static void main_printf_view ( void )//主页菜单
|
||||
{
|
||||
HideCursor ( );//隐藏光标
|
||||
system ( "cls" );//清屏
|
||||
|
||||
CursorJump ( 8 , 50 );
|
||||
color ( 2 );//设置颜色
|
||||
printf ( "欢迎使用学生管理系统" );
|
||||
CursorJump ( 9 , 48 );
|
||||
color ( 4 );//设置颜色
|
||||
printf ( "按下相应按键进入对应模式" );
|
||||
|
||||
CursorJump ( 10 , 47 );
|
||||
for ( int i = 0 ; i < 26 ; ++ i )
|
||||
{
|
||||
color ( 7 );//设置颜色
|
||||
printf ( "-" );
|
||||
}
|
||||
|
||||
CursorJump ( 11 , 52 );
|
||||
color ( 1 );//设置颜色
|
||||
printf ( "[Enter]" );
|
||||
color ( 7 );//设置颜色
|
||||
printf ( " 进入程序\n" );
|
||||
CursorJump ( 12 , 52 );
|
||||
color ( 1 );//设置颜色
|
||||
printf ( "[M]" );
|
||||
color ( 7 );//设置颜色
|
||||
printf ( "\t 管理课程" );
|
||||
|
||||
CursorJump ( 13 , 52 );
|
||||
color ( 1 );//设置颜色
|
||||
printf ( "[ESC]" );
|
||||
color ( 7 );//设置颜色
|
||||
printf ( " 退出程序\n" );
|
||||
|
||||
for ( int i = 6 ; i <= 15 ; ++ i )
|
||||
{
|
||||
for ( int j = 45 ; j <= 74 ; ++ j )
|
||||
{
|
||||
if ( i == 6 || i == 15 || j == 45 || j == 74 )
|
||||
{
|
||||
CursorJump ( i , j );
|
||||
color ( 7 );//设置颜色
|
||||
printf ( "■" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void main_move_snake(void)//移动小蛇
|
||||
{
|
||||
Sleep (80);
|
||||
CursorJump ( snake.tail[0] , snake.tail[1] );
|
||||
printf (" ");
|
||||
snake.tail[0]=snake.body[0];
|
||||
snake.tail[1]=snake.body[1];
|
||||
snake.body[0]=snake.head[0];
|
||||
snake.body[1]=snake.head[1];
|
||||
if(snake.head[0]==6&&snake.head[1]<74)
|
||||
{
|
||||
snake.head[1]++;
|
||||
}
|
||||
else if(snake.head[1]==74&&snake.head[0]<15)
|
||||
{
|
||||
snake.head[0]++;
|
||||
}
|
||||
else if(snake.head[0]==15&&snake.head[1]>45)
|
||||
{
|
||||
snake.head[1]--;
|
||||
}
|
||||
else if(snake.head[1]==45&&snake.head[0]>7)
|
||||
{
|
||||
snake.head[0]--;
|
||||
}
|
||||
else
|
||||
{
|
||||
snake.tail[0]=6;
|
||||
snake.tail[1]=45;
|
||||
snake.body[0]=6;
|
||||
snake.body[1]=46;
|
||||
snake.head[0]=6;
|
||||
snake.head[1]=47;
|
||||
main_printf_view();
|
||||
}
|
||||
color ( 13 );//设置颜色
|
||||
CursorJump ( snake.tail[0] , snake.tail[1] );
|
||||
printf ("□");
|
||||
CursorJump ( snake.body[0] , snake.body[1] );
|
||||
printf ("□");
|
||||
CursorJump ( snake.head[0] , snake.head[1] );
|
||||
printf ("■");
|
||||
}
|
||||
|
||||
//主函数
|
||||
int main ( void )
|
||||
{
|
||||
//定义变量
|
||||
static char start_pick = '0';//开始的选择
|
||||
snake.head[0]=7;
|
||||
snake.head[1]=45;
|
||||
srand ( ( unsigned ) time ( NULL ) );
|
||||
while ( 1 )
|
||||
{
|
||||
main_move_snake();//移动小蛇
|
||||
//获取用户的输入
|
||||
if ( _kbhit ( ) )
|
||||
{
|
||||
start_pick = ( char ) _getch ( );
|
||||
}
|
||||
//判断用户输入
|
||||
switch ( start_pick )
|
||||
{
|
||||
case ENTER:
|
||||
{
|
||||
start_pick = '0';
|
||||
system_start ( );//管理系统主页
|
||||
snake.head[0]=7;
|
||||
snake.head[1]=45;
|
||||
break;
|
||||
}
|
||||
case 'm':
|
||||
case 'M':
|
||||
{
|
||||
start_pick = '0';
|
||||
course_start ( );//管理系统主页
|
||||
snake.head[0]=7;
|
||||
snake.head[1]=45;
|
||||
break;
|
||||
}
|
||||
|
||||
case ESC:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
84
rust/temp/src/core/mod.rs
Normal file
84
rust/temp/src/core/mod.rs
Normal file
@ -0,0 +1,84 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
use tokio::io::{AsyncReadExt};
|
||||
use tokio::{net, runtime};
|
||||
use crate::request::{Method,Request};
|
||||
use crate::route::{Route};
|
||||
use crate::respond::{Respond};
|
||||
|
||||
pub struct Server {
|
||||
listener_addr: &'static str,
|
||||
listener_port: i32,
|
||||
status: bool,
|
||||
routes:RwLock<Vec<Route>>,
|
||||
}
|
||||
impl Server {
|
||||
pub fn new(listener_port:i32) -> Arc<Self> {
|
||||
if listener_port < 1 || listener_port > 65535 {
|
||||
panic!("listener port must be between 1 and 65535");
|
||||
}
|
||||
Arc::new(
|
||||
Self {
|
||||
listener_addr: "127.0.0.1",
|
||||
listener_port,
|
||||
status: false,
|
||||
routes: RwLock::new(Vec::new()),
|
||||
}
|
||||
)
|
||||
}
|
||||
pub fn start(self: Arc<Self>) {
|
||||
let address=format!("{}:{}", self.listener_addr, self.listener_port);
|
||||
let rt = runtime::Runtime::new().unwrap();
|
||||
println!("Listening on {}", address);
|
||||
let listener =rt.block_on(async { net::TcpListener::bind(address).await.expect("Failed to bind listener") });
|
||||
rt.block_on(self.receive(listener));
|
||||
}
|
||||
}
|
||||
|
||||
impl Server {
|
||||
async fn receive(self:Arc<Self>,listener:net::TcpListener) {
|
||||
loop {
|
||||
let (mut socket, _) = listener.accept().await.expect("Failed to accept connection");
|
||||
let server = self.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut buf = [0; 1024];
|
||||
if let Err(e) = socket.read(&mut buf).await {
|
||||
println!("Failed to read from socket: {}", e);
|
||||
return;
|
||||
}
|
||||
let content = match String::from_utf8(buf.to_vec()) {
|
||||
Ok(s) => s,
|
||||
Err(e1) => {
|
||||
println!("Failed to convert buffer to string: {}", e1);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let request = match Request::build(content) {
|
||||
Some(req) => req,
|
||||
None => {
|
||||
println!("Request parsing failed");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let respond=Respond::build(socket);
|
||||
for route in server.routes.read().expect("Unable to read route").iter() {
|
||||
if request.method() == &route.method {
|
||||
(route.function)(request, respond);
|
||||
return;
|
||||
}else {
|
||||
println!("Request parsing failed");
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Server {
|
||||
pub fn route(self:&Arc<Self>, path: &'static str, method: &'static str, function: impl Fn(Request, Arc<Respond>) + Send + Sync + 'static) {
|
||||
let test_method=method.to_uppercase().as_str().into();
|
||||
if test_method == Method::Uninitialized {panic!("该方法未被定义")}
|
||||
let route = Route { path, method:test_method, function: Box::new(function) };
|
||||
self.routes.write().expect("Route write failed").push(route);
|
||||
}
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
extern crate wasm_bindgen;
|
||||
use core::Server;
|
||||
mod core;
|
||||
mod request;
|
||||
mod respond;
|
||||
mod route;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
pub fn alert(s: &str);
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn greet(name: &str) {
|
||||
alert(&format!("Hello, {}!", name));
|
||||
fn main() {
|
||||
let server = Server::new( 8000);
|
||||
server.route("/","get",|request, respond| {
|
||||
respond.send();
|
||||
println!("{}",request.method())
|
||||
});
|
||||
server.start();
|
||||
}
|
102
rust/temp/src/request/mod.rs
Normal file
102
rust/temp/src/request/mod.rs
Normal file
@ -0,0 +1,102 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Display;
|
||||
pub enum Method {
|
||||
Get,
|
||||
Post,
|
||||
Uninitialized
|
||||
}
|
||||
|
||||
impl From<&str> for Method {
|
||||
fn from(s: &str) -> Method {
|
||||
match s{
|
||||
"GET" => Method::Get,
|
||||
"POST" => Method::Post,
|
||||
_ => Method::Uninitialized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Method {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let method = match self {
|
||||
Method::Get => {"GET"}
|
||||
Method::Post => {"POST"}
|
||||
Method::Uninitialized => {"Uninitialized"}
|
||||
};
|
||||
write!(f, "{}", method)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Method {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Method::Get, Method::Get) => true,
|
||||
(Method::Post, Method::Post) => true,
|
||||
(Method::Uninitialized, Method::Uninitialized) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Version {
|
||||
V1_1,
|
||||
Uninitialized
|
||||
}
|
||||
|
||||
impl From<&str> for Version {
|
||||
fn from(s: &str) -> Version {
|
||||
match s {
|
||||
"HTTP/1.1" => Version::V1_1,
|
||||
_ => Version::Uninitialized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Resource{
|
||||
Path(String),
|
||||
}
|
||||
|
||||
|
||||
pub struct Request{
|
||||
method: Method,
|
||||
version: Version,
|
||||
resource: Resource,
|
||||
headers: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl Request{
|
||||
pub fn build(content:String) -> Option<Request>{
|
||||
let mut content =content.lines();
|
||||
|
||||
let request_line =content.next().unwrap_or("");
|
||||
if request_line.is_empty(){return None}
|
||||
let request_line:Vec<_> = request_line.split_whitespace().collect();
|
||||
if request_line.len()<3 {return None}
|
||||
let method=request_line[0];
|
||||
let resource=request_line[1];
|
||||
let version=request_line[2];
|
||||
if method.is_empty()||resource.is_empty()||version.is_empty() {return None}
|
||||
|
||||
let mut headers =HashMap::<String, String>::new();
|
||||
for i in content {
|
||||
if i.len()==0 { break;}
|
||||
let parts:Vec<&str> = i.split(": ").collect();
|
||||
if parts.len() == 2 {
|
||||
headers.insert(parts[0].to_string(), parts[1].to_string());
|
||||
}
|
||||
};
|
||||
|
||||
Some(Request{
|
||||
method: method.into(),
|
||||
version: version.into(),
|
||||
resource: Resource::Path(resource.to_string()),
|
||||
headers,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Request {
|
||||
pub fn method(&self) -> &Method {
|
||||
&self.method
|
||||
}
|
||||
}
|
60
rust/temp/src/respond/mod.rs
Normal file
60
rust/temp/src/respond/mod.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::task;
|
||||
|
||||
pub struct Respond<'a>{
|
||||
version:&'a str,
|
||||
status_code:&'a str,
|
||||
status_message:&'a str,
|
||||
headers:HashMap<&'a str, &'a str>,
|
||||
body:&'a str,
|
||||
socket:Arc<Mutex<TcpStream>>
|
||||
}
|
||||
|
||||
|
||||
impl Respond<'_> {
|
||||
pub fn build(socket: TcpStream) -> Arc<Respond<'static>> {
|
||||
Arc::new(Respond {
|
||||
version: "HTTP/1.1",
|
||||
status_code: "200",
|
||||
status_message: "OK",
|
||||
headers: HashMap::new(),
|
||||
body: "Hello, world!",
|
||||
socket: Arc::new(Mutex::new(socket))
|
||||
})
|
||||
}
|
||||
fn format_message(self:Arc<Self>) -> String {
|
||||
let mut massage =String::new();
|
||||
let status_line= format!("{} {} {}\r\n", self.status_message,self.version,self.status_message);
|
||||
massage.push_str(&status_line);
|
||||
let mut header =String::new();
|
||||
for (key, value) in self.headers.iter() {
|
||||
header += &format!("{}: {}\r\n", key, value);
|
||||
}
|
||||
massage.push_str("\n\n");
|
||||
massage.push_str(self.body);
|
||||
massage
|
||||
}
|
||||
|
||||
pub fn send(self: Arc<Self>) {
|
||||
let socket = self.socket.clone();
|
||||
let message = self.format_message();
|
||||
|
||||
task::spawn(async move {
|
||||
let mut socket = socket.lock().await;
|
||||
if let Ok(_) = socket.write_all(message.as_ref()).await {
|
||||
if let Err(e) = socket.flush().await {
|
||||
println!("Failed to flush: {}", e);
|
||||
}
|
||||
} else {
|
||||
println!("Failed to send content");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
10
rust/temp/src/route/mod.rs
Normal file
10
rust/temp/src/route/mod.rs
Normal file
@ -0,0 +1,10 @@
|
||||
use std::sync::Arc;
|
||||
use crate::request::{Method, Request};
|
||||
use crate::respond::{Respond};
|
||||
|
||||
pub(crate) struct Route {
|
||||
pub path: &'static str,
|
||||
pub method: Method,
|
||||
pub function: Box<dyn Fn(Request,Arc<Respond>) + Send + Sync>,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user