示例
package main
import (
"fmt"
"log"
"net"
"runtime"
"time"
)
func Log(format string, v ...any) {
_, _, line, ok := runtime.Caller(1)
extend := []interface{}{line}
args := append(extend, v...)
if ok {
log.Printf("line %v:"+format, args...)
} else {
log.Printf(format, v...)
}
}
// 关键部分
func EchoHandle(conn net.Conn) {
defer conn.Close()
buf := make([]byte, 256)
length := 0
conn.SetDeadline(time.Time{})
for {
left := buf[length:]
n, err := conn.Read(left)
if err != nil {
log.Print(err)
return
}
length += n
Log("read %v bytes from socket", n)
fmt.Println("message: ", string(buf[:length]))
n, err = conn.Write(buf[:length])
if err != nil {
log.Print(err)
return
}
length -= n
Log("n=%v\n", n)
copy(buf, buf[n:])
Log("size=%v, len =%v, cap=%v\n", length, len(buf), cap(buf))
}
}
func main() {
listener, err := net.Listen("tcp", ":9000")
if err != nil {
fmt.Println("listen error: ", err)
return
}
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("accept error: ", err)
}
fmt.Println("connection peer: ", conn.LocalAddr())
go EchoHandle(conn)
}
}
我们把关注的放在EchoHanle
func EchoHandle(conn net.Conn) {
defer conn.Close()
buf := make([]byte, 256)
length := 0
conn.SetDeadline(time.Time{})
for {
left := buf[length:]
n, err := conn.Read(left)
if err != nil {
log.Print(err)
return
}
length += n
Log("read %v bytes from socket", n)
fmt.Println("message: ", string(buf[:length]))
n, err = conn.Write(buf[:length])
if err != nil {
log.Print(err)
return
}
length -= n
copy(buf, buf[n:])
}
}
这里有一些需要注意的地方。
- SetDeadline为空意味着这是可以一直阻塞的调用的
- 切片都是引用
看上去上面的代码还是有些杂乱,用buffer重构掉slice
func EchoHandle(conn net.Conn) {
defer conn.Close()
reader := bufio.NewReader(conn)
writer := bufio.NewWriter(conn)
rw := bufio.NewReadWriter(reader, writer)
for {
msg, err := rw.ReadString('\n')
if err != nil {
log.Print(err)
return
}
Log("read %v bytes from socket", len(msg))
fmt.Println("message: ", msg)
n, err := rw.WriteString(msg)
if err != nil {
if n < len(msg) {
log.Print("warning: ", err)
} else {
return
}
}
}
}
参考链接