这是我参与「第五届青训营 」笔记创作活动的第16天
TCP服务端可以接收多个客户端连接进行处理。服务端可以通过创建多个goroutine协程实现高并发处理连接请求。
go中通过net包实现网络编程。
服务端逻辑
- 监听端口
- 接收客户端的请求连接
- 创建goroutine处理请求
服务端代码如下所示:
func process(conn net.Conn) {
defer conn.Close() //关闭连接
for {
reader := bufio.NewReader(conn) //数据缓冲区
var buf [128]byte
n, err := reader.Read(buf[:]) //读取数据
if err != nil {
fmt.Printf("read err %v", err)
break
}
resv := string(buf[:n])
//接收到消息后,可以替换成自己的处理逻辑
fmt.Println("收到客户端发来消息", resv)
//通过Write方法回复消息
conn.Write([]byte(resv)) //发送数据
}
}
func main() {
// 服务器端开启端口
listen, err := net.Listen("tcp", "127.0.0.1:9999")
if err != nil {
fmt.Println("listen failed, err:", err)
return
}
for {
conn, err := listen.Accept() // 建立连接
if err != nil {
fmt.Println("accept failed, err:", err)
continue
}
go process(conn) // 启动一个goroutine处理连单独处理连接
}
}
客户端的逻辑如下:
- 建立与服务器的连接
- 进行数据的发送与接收
- 关闭连接
代码逻辑如下所示:
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:9999")
if err != nil {
fmt.Println("err :", err)
return
}
defer conn.Close() // 关闭连接
inputReader := bufio.NewReader(os.Stdin)
for {
input, _ := inputReader.ReadString('\n') // 读取用户输入
inputInfo := strings.Trim(input, "\r\n")
if strings.ToUpper(inputInfo) == "Q" { // 如果输入q就退出
return
}
_, err = conn.Write([]byte(inputInfo)) // 发送数据
if err != nil {
return
}
buf := [512]byte{}
n, err := conn.Read(buf[:])
if err != nil {
fmt.Println("recv failed, err:", err)
return
}
fmt.Println(string(buf[:n]))
}
}
运行server和client后,在client的控制台下输入消息如下所示:
服务器端会打印消息,然后恢复客户端,我们可以将打印的逻辑替换成自己处理消息的逻辑。
服务器回复的消息如下所示