我们在消息的头部添加一个固定长度的字段(例如4字节),用于表示消息的实际长度。这样接收方在读取消息时,可以先读取前4字节获取消息长度,然后根据该长度读取完整的消息内容。
package main
import (
"bufio"
"encoding/binary"
"fmt"
"io"
"net"
)
const headerLength = 4 // 消息长度字段的字节数
func main() {
// 监听端口
listener, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println("Error listening:", err)
return
}
defer listener.Close()
fmt.Println("Server listening on :8080")
for {
// 接受客户端连接
conn, err := listener.Accept()
if err != nil {
fmt.Println("Error accepting connection:", err)
continue
}
fmt.Println("Client connected:", conn.RemoteAddr())
// 处理客户端连接
go handleClient(conn)
}
}
func handleClient(conn net.Conn) {
defer conn.Close()
reader := bufio.NewReader(conn)
for {
// 读取消息长度(前4字节)
header := make([]byte, headerLength)
_, err := io.ReadFull(reader, header)
if err != nil {
if err == io.EOF {
fmt.Println("Client disconnected:", conn.RemoteAddr())
} else {
fmt.Println("Error reading header:", err)
}
return
}
// 解析消息长度
msgLength := int(binary.BigEndian.Uint32(header))
fmt.Printf("Message length: %d\n", msgLength)
// 读取消息内容
msg := make([]byte, msgLength)
_, err = io.ReadFull(reader, msg)
if err != nil {
fmt.Println("Error reading message:", err)
return
}
// 处理消息
message := string(msg)
fmt.Printf("Received message from %s: %s\n", conn.RemoteAddr(), message)
// 回显消息
response := "Server received: " + message
sendMessage(conn, []byte(response))
}
}
func sendMessage(conn net.Conn, data []byte) {
// 构造消息头(4字节长度)
length := uint32(len(data))
header := make([]byte, headerLength)
binary.BigEndian.PutUint32(header, length)
// 发送消息头和消息内容
_, err := conn.Write(append(header, data...))
if err != nil {
fmt.Println("Error sending message:", err)
}
}
客户端代码
package main
import (
"bufio"
"encoding/binary"
"fmt"
"io"
"net"
"os"
)
const headerLength = 4 // 消息长度字段的字节数
func main() {
// 连接到服务端
conn, err := net.Dial("tcp", "localhost:8080")
if err != nil {
fmt.Println("Error connecting to server:", err)
return
}
defer conn.Close()
fmt.Println("Connected to server")
// 启动一个goroutine接收服务端消息
go receiveMessages(conn)
// 从控制台读取用户输入并发送到服务端
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
message := scanner.Text()
sendMessage(conn, []byte(message))
}
if err := scanner.Err(); err != nil {
fmt.Println("Error reading input:", err)
}
}
func receiveMessages(conn net.Conn) {
reader := bufio.NewReader(conn)
for {
// 读取消息长度(前4字节)
header := make([]byte, headerLength)
_, err := io.ReadFull(reader, header)
if err != nil {
if err == io.EOF {
fmt.Println("Disconnected from server")
} else {
fmt.Println("Error reading header:", err)
}
os.Exit(0)
}
// 解析消息长度
msgLength := int(binary.BigEndian.Uint32(header))
fmt.Printf("Message length: %d\n", msgLength)
// 读取消息内容
msg := make([]byte, msgLength)
_, err = io.ReadFull(reader, msg)
if err != nil {
fmt.Println("Error reading message:", err)
os.Exit(0)
}
// 显示消息
message := string(msg)
fmt.Printf("Received from server: %s\n", message)
}
}
func sendMessage(conn net.Conn, data []byte) {
// 构造消息头(4字节长度)
length := uint32(len(data))
header := make([]byte, headerLength)
binary.BigEndian.PutUint32(header, length)
// 发送消息头和消息内容
_, err := conn.Write(append(header, data...))
if err != nil {
fmt.Println("Error sending message:", err)
}
}