net包练习
//server.go
package main
import (
"bufio"
"fmt"
"io/ioutil"
"net"
"os"
"path/filepath"
"strings"
)
//这里的独写用的是小文件 如果文件较大适合用bufio 或者read 分批次字节切片读取
var (
binPath string
dirPath string
defaultFileName string
file404 string
file500 string
)
func Header(conn net.Conn) {
defer func() {
conn.Close()
fmt.Println("client closed",conn.RemoteAddr())
}()
fmt.Println("Client Connected:",conn.RemoteAddr())
//处理客户端数据
reader := bufio.NewReader(conn)
//读取数据
line,err := reader.ReadString('\n')
if err != nil {
fmt.Println(err)
}else {
//正常处理
nodes := strings.Fields(line)
//获取请求资源(本地)路径
path := filepath.Join(dirPath,nodes[1])
//如果请求路径报错的话 判断
if info,err := os.Stat(path);err != nil {
//不存在 返回404的路径
if os.IsNotExist(err){
path = file404
//不是因为不存在报错返回500
}else {
path = file500
}
}else {
//判断请求路径存在的话是目录还是文件
//是目录默认返回index.html
if info.IsDir(){
path = filepath.Join(path,defaultFileName)
}
////是文件就直接返回
}
//再次对path进行检查(404.html/500.html/index.html)
if _,err := os.Stat(path);err == nil {
//fprint 写入文件
fmt.Fprint(conn,"HTTP/1.1 %v 200 OK\r\n")
fmt.Fprint(conn,"Server:aaserver \r\n")
fmt.Fprint(conn,"\r\n")
bytes,_ := ioutil.ReadFile(path)
conn.Write(bytes)
}else {
fmt.Println(err)
}
}
}
func main() {
//获取当前运行文件的路径
binPath,_ = filepath.Abs(os.Args[0])
//获取父目录
dirPath = filepath.Dir(binPath)
//默认路径
defaultFileName = "index.html"
//错误路径
file404 = filepath.Join(dirPath,"404.html")
file500 = filepath.Join(dirPath,"500.html")
addr := ":9999"
//监听端口
listener,err := net.Listen("tcp",addr)
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
//延迟关闭
defer listener.Close()
fmt.Println("Listen on",listener.Addr())
for {
//获取请求
conn,err := listener.Accept()
if err != nil {
fmt.Println(err)
continue
}
//用例程可以实现多并发处理请求
go Header(conn)
}
}
//client.go
package main
import (
"bufio"
"fmt"
"io"
"net"
"os"
)
func main() {
addr := "127.0.0.1:9999"
url := "/once.go"
client,err := net.Dial("tcp",addr)
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
fmt.Fprintf(client,"Get %s HTTP/1.0\r\n",url)
reader := bufio.NewReader(client)
line,err := reader.ReadString('\n')
fmt.Println("请求行:")
fmt.Println("\t",line)
fmt.Println("请求头:")
for {
line,err := reader.ReadString('\n')
if err != nil {
if err != io.EOF{
fmt.Println(err)
}
break
}
if line == "\r\n" {
break
}
//因为line就自带换行所以用print打印
fmt.Print("\t",line)
}
fmt.Println("响应体:")
for {
line, err := reader.ReadString('\n')
if err != nil {
if err != io.EOF {
fmt.Println(err)
}
break
}
if line == "\r\n" {
break
}
//因为line就自带换行所以用print打印
fmt.Print("\t", line)
}
client.Close()
}