第二十七篇:socket练习(1):实现浏览器静态文件的访问、处理404

一:代码格式整理:先将服务端代码中响应浏览器的代码函数 拎出来放到服务端包中

 

 二:代码

服务端代码:

 

 

 

package main
import (
	"fmt"
	"net"
	"runtime"
	"time"
)
func main()  {
	lis,err:=net.Listen("tcp","127.0.0.1:8099")
	if err !=nil{
		fmt.Println(err.Error())
		return
	}
	defer lis.Close()
	fmt.Println("创建监听成功,等待客户端连接")
	go func() {
		//写一个死循环每两秒进行打印输出
		for  {
			fmt.Printf("当前任务数:%d\n",runtime.NumGoroutine())
			time.Sleep(time.Second*2)
		}
	}()
	for {
		client,err:=lis.Accept()

		if err !=nil{
			fmt.Println(err.Error())
			return
		}
/*		每当有客户端连接的时候,就开一个协程
		改造代码很简单,直接加上 go 即可以;*/
		go func(c net.Conn){
			defer c.Close()
			buf:=make([]byte,4096)
			//服务端读
			n,err:=c.Read(buf)
			if err !=nil{
				fmt.Println(err.Error())
				return
			}
		/*	if GetRequestPath(string(buf[0:n]))=="/delay"{
				time.Sleep(time.Second*5)
			}*/
			//服务端发送
			c.Write([]byte(response(ReadHtml(GetRequestPath(string(buf[:n]))))))
		}(client)
	}
}

 包中代码:

 

 

 

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
)

func GetRequestPath(rq string) string{
	r:=regexp.MustCompile(`GET\s(.*?)\sHTTP`)
	if r.MatchString(rq){
		return r.FindStringSubmatch(rq)[1]
	}else {
		return "/"
	}
}
func response(body []byte)string{
	str:=`HTTP/1.1 200 OK
	Server:myServer
	Content-Type:text/html
	

%s
`
	/*
	%s为占位符 可以将传递的body,
	无论是字符还是切片都可以进行格式化;
	*/
	ret:=fmt.Sprintf(str,body)
	return ret
}
//判断文件是否存在
func ExistsFile(path string) (bool,error){
	//os.Stat(path) path可以是绝对路径,也可以是相对路径返回文件相关信息;
	_,err:=os.Stat("./web"+path)
	if err==nil{
		return true,nil
	}else {
		//os.IsNotExist 判断不存在
		if os.IsNotExist(err){
			return  false,err
		}else{//其它错误(比如权限不足等)
			return false,err
		}
	}
}
//如果文件存在则读取
func ReadHtml(path string)[]byte{
	exist,_:=ExistsFile(path)
	if exist{
		//这里可以使用ioutil.ReadAll也可以使用ioutil.ReadFile
		//如果使用ioutil.ReadAll需要使用os.OPen先把文件给打开;
		file,_:=ioutil.ReadFile("./web"+path)

		return file
	}else {
		return []byte("404")
	}
}

 默认首页:

 

 

浏览器请求如下:

 

 

 

 这里404的状态码有问题,如下:

 

 

 

 

整体代码修改优化如下:

(1):定义状态码结构体

 

 (2):服务端代码:

package main
import (
	"fmt"
	"net"
	"runtime"
	"time"
)
func main()  {
	lis,err:=net.Listen("tcp","127.0.0.1:8099")
	if err !=nil{
		fmt.Println(err.Error())
		return
	}
	defer lis.Close()
	fmt.Println("创建监听成功,等待客户端连接")
	go func() {
		//写一个死循环每两秒进行打印输出
		for  {
			fmt.Printf("当前任务数:%d\n",runtime.NumGoroutine())
			time.Sleep(time.Second*2)
		}
	}()
	for {
		client,err:=lis.Accept()

		if err !=nil{
			fmt.Println(err.Error())
			return
		}
/*		每当有客户端连接的时候,就开一个协程
		改造代码很简单,直接加上 go 即可以;*/
		go func(c net.Conn){
			defer c.Close()
			buf:=make([]byte,4096)
			//服务端读
			n,err:=c.Read(buf)
			if err !=nil{
				fmt.Println(err.Error())
				return
			}
		/*	if GetRequestPath(string(buf[0:n]))=="/delay"{
				time.Sleep(time.Second*5)
			}*/
			//服务端发送
			c.Write([]byte(ReadHtml(GetRequestPath(string(buf[:n])))))
		}(client)
	}
}

 (3):netutil包函数

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
)

func GetRequestPath(rq string) string{
	r:=regexp.MustCompile(`GET\s(.*?)\sHTTP`)
	if r.MatchString(rq){
		return r.FindStringSubmatch(rq)[1]
	}else {
		return "/"
	}
}
func response(body []byte,status HttpStatus)string{
str:=`HTTP/1.1 %d %s
Server:myServer
Content-Type:text/html


%s
`
/*
%s为占位符 可以将传递的body,
无论是字符还是切片都可以进行格式化;
*/
ret:=fmt.Sprintf(str,status.Code,status.Message,body)
return ret
}
//判断文件是否存在 func ExistsFile(path string) (bool,error){ //os.Stat(path) path可以是绝对路径,也可以是相对路径返回文件相关信息; _,err:=os.Stat("./web"+path) if err==nil{ return true,nil }else { //os.IsNotExist 判断不存在 if os.IsNotExist(err){ return false,err }else{//其它错误(比如权限不足等) return false,err } } } //如果文件存在则读取 func ReadHtml(path string)string{ exist,_:=ExistsFile(path) if exist{ //这里可以使用ioutil.ReadAll也可以使用ioutil.ReadFile //如果使用ioutil.ReadAll需要使用os.OPen先把文件给打开; file,_:=ioutil.ReadFile("./web"+path) response(file,NewHttpStatus(200,"ok")) }else { response([]byte("404"),NewHttpStatus(404,"Not Found")) } }

 

浏览器请求如下:

 

 

posted @ 2020-06-18 13:20  痞子胥  阅读(160)  评论(0)    收藏  举报