一、概述
上一篇实现了一个server和client通信,完成了小写转大写的功能,但是是一个单任务式的响应:客户端发送连接接收响应,程序结束;服务端则接收数据响应数据也结束!就实际需要而言,并没有很大的用处,所以现在我们就给客户端和服务端添加上并发功能。
逻辑其实很简单,就是利用golang的gorutine,一旦来新的连接,就开启一个gorutine去处理,然后响应,直到客户端关闭连接。
二、服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| package main import ( "net" "fmt" "strings" ) func handle(conn net.Conn){ defer conn.Close() fmt.Println("Connect :", conn.RemoteAddr()) for { data := make([]byte, 2048) n, err := conn.Read(data) if n == 0{ fmt.Printf("%s has disconnect", conn.RemoteAddr()) break } if err != nil{ fmt.Println(err) continue } fmt.Printf("Receive data [%s] from [%s]", string(data[:n]), conn.RemoteAddr()) rspData := strings.ToUpper(string(data[:n])) _, err = conn.Write([]byte(rspData)) if err != nil{ fmt.Println(err) continue } } } func main(){ listener, err := net.Listen("tcp", ":8899") if err != nil{ fmt.Println(err) return } fmt.Println("Start listen localhost:8899") for { conn, err := listener.Accept() if err != nil{ fmt.Println(err) return } go handle(conn) } }
|
三、客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import ( "net" "fmt" ) func main(){ conn, err := net.Dial("tcp", ":8899") if err != nil{ fmt.Println(err) return } fmt.Println("Connect to localhost:8899 success") defer conn.Close() for{ fmt.Print("Please input send data :") var a string fmt.Scan(&a) if a == "exit"{break} _, err := conn.Write([]byte(a)) if err != nil{ fmt.Println(err) return } data := make([]byte, 2048) n, err := conn.Read(data) if err != nil{ fmt.Println(err) continue } fmt.Println("Response data :", string(data[:n])) } }
|
四、运行
此时,我们开启一个服务端,开启两个客户端进行测试:
至此,一个完美的多并发服务端就完成了!