diff --git a/networkProgram/NetworkProgram.log b/networkProgram/NetworkProgram.log index 4064c7a..639691c 100644 --- a/networkProgram/NetworkProgram.log +++ b/networkProgram/NetworkProgram.log @@ -17,3 +17,20 @@ IPv4这个版本规定,网络地址由32个二进制位组成,我们通常 也就是说,我们还需要一个参数,表示这个数据包到底供哪个程序(进程)使用。这个参数就叫做"端口”(port),它其实是每一个使用网卡的程序的编号。 每个数据包都发到主机的特定端口,所以不同的程序就能取到自己所需要的数据。 “端口"是0到65535之间的一个整数,正好16个二进制位。0到1023的端口被系统占用,用户只能选用大于1023的端口。有了IP和端口我们就能实现唯一确定互联网上一个程序,进而实现网络间的程序通信。 + + +TCP服务端程序的处理流程: + +1.监听端口 +2.接收客户端请求建立链接 +3.创建goroutine处理链接。 + +一个TCP客户端进行TCP通信的流程如下: + +1.建立与服务端的链接 +2.进行数据收发 +3.关闭链接 + +TCP粘包 +引申知识点: +大端和小端{https://zhuanlan.zhihu.com/p/680366680} \ No newline at end of file diff --git a/networkProgram/TCP_client.go b/networkProgram/TCP/TCP_client.go similarity index 100% rename from networkProgram/TCP_client.go rename to networkProgram/TCP/TCP_client.go diff --git a/networkProgram/TCP_server.go b/networkProgram/TCP/TCP_server.go similarity index 94% rename from networkProgram/TCP_server.go rename to networkProgram/TCP/TCP_server.go index c1861d6..a0ba572 100644 --- a/networkProgram/TCP_server.go +++ b/networkProgram/TCP/TCP_server.go @@ -12,10 +12,11 @@ import ( //TCP server端 func process(conn net.Conn) { + defer conn.Close() var tmp = make([]byte, 1024) reader := bufio.NewReader(os.Stdin) for { - n, err := conn.Read(tmp[:]) + n, err := conn.Read(tmp) if err != nil { log.Fatal("read failed on:", err) return diff --git a/networkProgram/TCP/packet_splicing_client.go b/networkProgram/TCP/packet_splicing_client.go new file mode 100644 index 0000000..ce6dad1 --- /dev/null +++ b/networkProgram/TCP/packet_splicing_client.go @@ -0,0 +1,28 @@ +package main + +import ( + "fmt" + "net" + + "course/networkProgram/protocol" +) + +// socket_stick/client/main.go + +func main() { + conn, err := net.Dial("tcp", "127.0.0.1:30000") + if err != nil { + fmt.Println("dial failed, err", err) + return + } + defer conn.Close() + for i := 0; i < 20; i++ { + msg := `Hello, Hello. How are you?` + b, err := proto.Encode(msg) + if err != nil { + fmt.Println("encode failed, err", err) + } + conn.Write(b) + //time.Sleep(1 * time.Second) + } +} diff --git a/networkProgram/TCP/packet_splicing_server.go b/networkProgram/TCP/packet_splicing_server.go new file mode 100644 index 0000000..54656fc --- /dev/null +++ b/networkProgram/TCP/packet_splicing_server.go @@ -0,0 +1,44 @@ +package main + +import ( + "bufio" + proto "course/networkProgram/protocol" + "fmt" + "io" + "net" +) + +// socket_stick/server/main.go +func proc(conn net.Conn) { + defer conn.Close() + reader := bufio.NewReader(conn) + for { + msg, err := proto.Decode(reader) + if err == io.EOF { + return + } + if err != nil { + fmt.Println("decode msg failed, err:", err) + return + } + fmt.Println("收到client发来的数据:", msg) + } +} + +func main() { + + listen, err := net.Listen("tcp", "127.0.0.1:30000") + if err != nil { + fmt.Println("listen failed, err:", err) + return + } + defer listen.Close() + for { + conn, err := listen.Accept() + if err != nil { + fmt.Println("accept failed, err:", err) + continue + } + go proc(conn) + } +} diff --git a/networkProgram/UDP/udp_client.go b/networkProgram/UDP/udp_client.go new file mode 100644 index 0000000..84c95fb --- /dev/null +++ b/networkProgram/UDP/udp_client.go @@ -0,0 +1,39 @@ +package main + +import ( + "bufio" + "fmt" + "log" + "net" + "os" +) + +//UDP client + +func main() { + socket, err := net.DialUDP("udp", nil, &net.UDPAddr{ + IP: net.IPv4(127, 0, 0, 1), + Port: 40000, + }) + if err != nil { + log.Fatal("连接服务端失败,err", err) + return + } + defer socket.Close() + reader := bufio.NewReader(os.Stdin) + reply := make([]byte, 512) + for { + fmt.Print("> ") + msg, _ := reader.ReadString('\n') + socket.Write([]byte(msg)) + //收回复的数据 + n, _, err := socket.ReadFromUDP(reply) + if err != nil { + fmt.Println("read reply msg failed:", err) + return + } + fmt.Print(string(reply[:n])) + + } + +} diff --git a/networkProgram/UDP/udp_server.go b/networkProgram/UDP/udp_server.go new file mode 100644 index 0000000..b02a0c3 --- /dev/null +++ b/networkProgram/UDP/udp_server.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "log" + "net" + "strings" +) + +// UDP sever +func main() { + conn, err := net.ListenUDP("udp", &net.UDPAddr{ + IP: net.IPv4(127, 0, 0, 1), + Port: 40000, + }) + if err != nil { + log.Fatal("listen udp failed:", err) + return + } + defer conn.Close() + //不需要建立链接,直接收发数据 + data := make([]byte, 1024) + for { + n, addr, err := conn.ReadFromUDP(data) + if err != nil { + log.Println("read from udp failed:", err) + } + fmt.Printf("%s\n", data[:n]) + reply := string(data[:n]) + reply = strings.ToUpper(reply) + //发送数据 + conn.WriteToUDP([]byte(reply), addr) + } +} diff --git a/networkProgram/protocol/protocol.go b/networkProgram/protocol/protocol.go new file mode 100644 index 0000000..546360e --- /dev/null +++ b/networkProgram/protocol/protocol.go @@ -0,0 +1,50 @@ +// socket_stick/proto/proto.go +package proto + +import ( + "bufio" + "bytes" + "encoding/binary" +) + +// Encode 将消息编码 +func Encode(message string) ([]byte, error) { + // 读取消息的长度,转换成int32类型(占4个字节) + var length = int32(len(message)) + var pkg = new(bytes.Buffer) + // 写入消息头 + err := binary.Write(pkg, binary.LittleEndian, length) + if err != nil { + return nil, err + } + // 写入消息实体 + err = binary.Write(pkg, binary.LittleEndian, []byte(message)) + if err != nil { + return nil, err + } + return pkg.Bytes(), nil +} + +// Decode 解码消息 +func Decode(reader *bufio.Reader) (string, error) { + // 读取消息的长度 + lengthByte, _ := reader.Peek(4) // 读取前4个字节的数据 + lengthBuff := bytes.NewBuffer(lengthByte) + var length int32 + err := binary.Read(lengthBuff, binary.LittleEndian, &length) + if err != nil { + return "", err + } + // Buffered返回缓冲中现有的可读取的字节数。 + if int32(reader.Buffered()) < length+4 { + return "", err + } + + // 读取真正的消息数据 + pack := make([]byte, int(4+length)) + _, err = reader.Read(pack) + if err != nil { + return "", err + } + return string(pack[4:]), nil +}