Browse Source

network基本设计

yjp 1 year ago
parent
commit
85e6caf632
3 changed files with 191 additions and 0 deletions
  1. 157 0
      network/connection.go
  2. 34 0
      network/data_reader.go
  3. 0 0
      network/data_writer.go

+ 157 - 0
network/connection.go

@@ -0,0 +1,157 @@
+package network
+
+import (
+	"fmt"
+	"net"
+	"time"
+)
+
+// ConnectionReadOptions 从连接读取数据的选项
+type ConnectionReadOptions func(conn net.Conn) error
+
+// WithReadDeadline 读超时选项
+func WithReadDeadline(duration time.Duration) ConnectionReadOptions {
+	return func(conn net.Conn) error {
+		err := conn.SetReadDeadline(time.Now().Add(duration))
+		if err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
+
+// ConnectionWriteOptions 从连接写入数据的选项
+type ConnectionWriteOptions func(conn net.Conn) error
+
+// WithWriteDeadline 写超时选项
+func WithWriteDeadline(duration time.Duration) ConnectionWriteOptions {
+	return func(conn net.Conn) error {
+		err := conn.SetWriteDeadline(time.Now().Add(duration))
+		if err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
+
+// ReadUDP 读取UDP包
+func ReadUDP(conn *net.UDPConn, bufferSize int, opts ...ConnectionReadOptions) ([]byte, *net.UDPAddr, error) {
+	buffer := make([]byte, bufferSize)
+
+	for _, opt := range opts {
+		err := opt(conn)
+		if err != nil {
+			return nil, nil, err
+		}
+	}
+
+	n, rAddr, err := conn.ReadFromUDP(buffer)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	return buffer[:n], rAddr, nil
+}
+
+// WriteUDPWithRemoteAddr 指定远端(对端)地址写出UDP包
+func WriteUDPWithRemoteAddr(conn *net.UDPConn, rAddr *net.UDPAddr, data []byte, opts ...ConnectionWriteOptions) error {
+	for _, opt := range opts {
+		err := opt(conn)
+		if err != nil {
+			return err
+		}
+	}
+
+	_, err := conn.WriteToUDP(data, rAddr)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// WriteUDP 写出UDP包
+func WriteUDP(conn *net.UDPConn, data []byte, opts ...ConnectionWriteOptions) error {
+	for _, opt := range opts {
+		err := opt(conn)
+		if err != nil {
+			return err
+		}
+	}
+
+	_, err := conn.Write(data)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// ReadTCP 读取TCP数据
+func ReadTCP(conn net.Conn, bufferSize int, readCallback func(data []byte) (bool, error), opts ...ConnectionReadOptions) error {
+	for {
+		buffer := make([]byte, bufferSize)
+
+		for _, opt := range opts {
+			err := opt(conn)
+			if err != nil {
+				return err
+			}
+		}
+
+		n, err := conn.Read(buffer)
+		if err != nil {
+			return err
+		}
+
+		if n != 0 {
+			readOver, err := readCallback(buffer[:n])
+			if err != nil {
+				return err
+			}
+
+			if readOver {
+				return nil
+			}
+		}
+	}
+}
+
+// WriteTCP 写TCP数据
+func WriteTCP(conn net.Conn, data []byte, opts ...ConnectionWriteOptions) error {
+	writeBytesCount := 0
+
+	for {
+		for _, opt := range opts {
+			err := opt(conn)
+			if err != nil {
+				return err
+			}
+		}
+
+		n, err := conn.Write(data[writeBytesCount:])
+		if err != nil {
+			return err
+		}
+
+		writeBytesCount += n
+		if writeBytesCount < len(data) {
+			continue
+		}
+
+		return nil
+	}
+}
+
+// CloseConnection 关闭连接
+func CloseConnection(conn net.Conn) {
+	err := conn.Close()
+	if err != nil {
+		fmt.Println("Close Connection Error:", err.Error())
+		return
+	}
+
+	conn = nil
+}

+ 34 - 0
network/data_reader.go

@@ -0,0 +1,34 @@
+package network
+
+import (
+	"bytes"
+	"io"
+)
+
+// ReadBigEndianString 大端读取字符串 TODO 考虑改为一个网络字节序得写入和读取器
+func ReadBigEndianString(bigEndianBytes []byte) (string, error) {
+	// 使用bytes.Buffer来模拟一个io.Reader
+	reader := bytes.NewReader(bigEndianBytes)
+
+	// 初始化一个buffer,用于存放读取的字符串
+	var buffer []byte
+
+	// 使用binary.Read以大端模式读取字符串
+	// 因为字符串可能包含\x00,所以需要读取到\x00为止
+	for {
+		b := make([]byte, 1)
+
+		_, err := reader.Read(b)
+		if err != nil && err != io.EOF {
+			return "", err
+		}
+
+		if b[0] == 0 {
+			break
+		}
+
+		buffer = append(buffer, b...)
+	}
+
+	return string(buffer), nil
+}

+ 0 - 0
network/common.go → network/data_writer.go