package netProgram import ( "encoding/gob" "errors" "fmt" "io" "log" "math/rand" "net" "sync" "time" ) // 客户端 func TcpClient() { // tcp服务端地址 //serverAddress := "127.0.0.1:5678" // tcp协议类型 serverAddress := "[::1]:5678" // IPv6 //serverAddress := "127.0.0.1:5678" // IPv4 // 模拟多客户端 // 并发的客户端请求 num := 10 wg := sync.WaitGroup{} wg.Add(num) for i := 0; i < num; i++ { // 并发请求 go func(wg *sync.WaitGroup) { defer wg.Done() // A. 建立连接 conn, err := net.Dial(tcp, serverAddress) if err != nil { log.Println(err) return } // 保证关闭 defer conn.Close() log.Printf("connection is establish, client addr is %s\n", conn.LocalAddr()) }(&wg) } wg.Wait() } func TcpTimeoutClient() { // tcp服务端地址 serverAddress := "192.168.110.123:5678" // IPv6 4 // 模拟多客户端 // 并发的客户端请求 num := 10 wg := sync.WaitGroup{} wg.Add(num) for i := 0; i < num; i++ { // 并发请求 go func(wg *sync.WaitGroup) { defer wg.Done() // A. 建立连接 conn, err := net.DialTimeout(tcp, serverAddress, time.Second) //conn, err := net.Dial(tcp, serverAddress) if err != nil { log.Println(err) return } // 保证关闭 defer conn.Close() log.Printf("connection is establish, client addr is %s\n", conn.LocalAddr()) }(&wg) } wg.Wait() } func TcpBacklogClient() { // tcp服务端地址 serverAddress := "127.0.0.1:5678" // IPv6 4 // 模拟多客户端 // 并发的客户端请求 num := 256 wg := sync.WaitGroup{} wg.Add(num) for i := 0; i < num; i++ { // 并发请求 go func(wg *sync.WaitGroup, no int) { defer wg.Done() // A. 建立连接 conn, err := net.DialTimeout(tcp, serverAddress, time.Second) //conn, err := net.Dial(tcp, serverAddress) if err != nil { log.Println(err) return } // 保证关闭 defer conn.Close() log.Printf("%d: connection is establish, client addr is %s\n", no, conn.LocalAddr()) }(&wg, i) time.Sleep(30 * time.Millisecond) } wg.Wait() } func TcpClientRW() { // tcp服务端地址 serverAddress := "127.0.0.1:5678" // IPv6 4 // A. 建立连接 conn, err := net.DialTimeout(tcp, serverAddress, time.Second) //conn, err := net.Dial(tcp, serverAddress) if err != nil { log.Println(err) return } // 保证关闭 defer conn.Close() log.Printf("connection is establish, client addr is %s\n", conn.LocalAddr()) // B.从服务端接收数据,SerRead buf := make([]byte, 1024) rn, err := conn.Read(buf) if err != nil { log.Println(err) } log.Println("received from server data is:", string(buf[:rn])) // C.向服务器端发送数据,SerWrite wn, err := conn.Write([]byte("send some data from client" + "\n")) if err != nil { log.Println(err) } log.Printf("client write len is %d\n", wn) } func TcpWClient() { // tcp服务端地址 serverAddress := "127.0.0.1:5678" // IPv6 4 // A. 建立连接 conn, err := net.DialTimeout(tcp, serverAddress, time.Second) //conn, err := net.Dial(tcp, serverAddress) if err != nil { log.Println(err) return } // 保证关闭 defer conn.Close() log.Printf("connection is establish, client addr is %s\n", conn.LocalAddr()) // //select {} // 1. 阻塞Read //buf := make([]byte, 1024) //rn, err := conn.SerRead(buf) //if err != nil { // log.Println(err) //} //log.Println("received from server data is:", string(buf[:rn])) // 2. 循环读 conn.SetReadDeadline(time.Now().Add(10 * time.Second)) for { buf := make([]byte, 10) rn, err := conn.Read(buf) if err != nil { log.Println(err) break } log.Println("received from server data is:", string(buf[:rn])) } } func TcpClientRWConcurrency() { // tcp服务端地址 serverAddress := "127.0.0.1:5678" // IPv6 4 // A. 建立连接 conn, err := net.DialTimeout(tcp, serverAddress, time.Second) //conn, err := net.Dial(tcp, serverAddress) if err != nil { log.Println(err) return } // 保证关闭 defer conn.Close() log.Printf("connection is establish, client addr is %s\n", conn.LocalAddr()) wg := sync.WaitGroup{} // 并发的写 wg.Add(1) go CliWrite(conn, &wg) // 并发的读 wg.Add(1) go CliRead(conn, &wg) wg.Wait() } func CliWrite(conn net.Conn, wg *sync.WaitGroup) { defer wg.Done() for { // B.向客户端发送数据,SerWrite wn, err := conn.Write([]byte("send some data from client" + "\n")) if err != nil { log.Println(err) } log.Printf("client write len is %d\n", wn) time.Sleep(3 * time.Second) } } func CliRead(conn net.Conn, wg *sync.WaitGroup) { defer wg.Done() for { // C.从客户端接收数据,SerRead buf := make([]byte, 1024) rn, err := conn.Read(buf) if err != nil { log.Println(err) } log.Println("received from server data is:", string(buf[:rn])) } } func TcpClientFormat() { // tcp服务端地址 serverAddress := "127.0.0.1:5678" // IPv6 4 // A. 建立连接 conn, err := net.DialTimeout(tcp, serverAddress, time.Second) //conn, err := net.Dial(tcp, serverAddress) if err != nil { log.Println(err) return } // 保证关闭 defer conn.Close() log.Printf("connection is establish, client addr is %s\n", conn.LocalAddr()) wg := sync.WaitGroup{} // 接收端 wg.Add(1) go CliReadFormat(conn, &wg) wg.Wait() } func CliReadFormat(conn net.Conn, wg *sync.WaitGroup) { defer wg.Done() for { // 从客户端接收数据 // 接收到数据后,先解码 // 传递的消息类型 type Message struct { ID uint `json:"id,omitempty"` Code string `json:"code,omitempty"` Content string `json:"content,omitempty"` } message := Message{} // 1, JSON解码 //// 创建解码器 //decoder := json.NewDecoder(conn) //// 利用解码器进行解码 //// 解码操作,从conn中读取内容,成功会将解码后的结果,赋值到message变量 //if err := decoder.Decode(&message); err != nil { // log.Println(err) // continue //} //log.Println(message) // 2, GOB解码 // 创建解码器 decoder := gob.NewDecoder(conn) // 利用解码器进行解码 // 解码操作,从conn中读取内容,成功会将解码后的结果,赋值到message变量 if err := decoder.Decode(&message); err != nil { log.Println(err) continue } log.Println(message) } } // 短连接示例 func TcpClientSort() { // tcp服务端地址 serverAddress := "127.0.0.1:5678" // IPv6 4 // A. 建立连接 conn, err := net.DialTimeout(tcp, serverAddress, time.Second) if err != nil { log.Println(err) return } // 保证关闭 defer conn.Close() log.Printf("connection is establish, client addr is %s\n", conn.LocalAddr()) wg := sync.WaitGroup{} // 接收端 wg.Add(1) go CliReadSort(conn, &wg) wg.Wait() } func CliReadSort(conn net.Conn, wg *sync.WaitGroup) { defer wg.Done() // 传递的消息类型 type Message struct { ID uint `json:"id,omitempty"` Code string `json:"code,omitempty"` Content string `json:"content,omitempty"` } message := Message{} for { // 从客户端接收数据 // 接收到数据后,先解码 // GOB解码 // 创建解码器 decoder := gob.NewDecoder(conn) // 利用解码器进行解码 // 解码操作,从conn中读取内容,成功会将解码后的结果,赋值到message变量 err := decoder.Decode(&message) // 错误 io.EOF 时,表示连接被给关闭 if err != nil && errors.Is(err, io.EOF) { log.Println(err) log.Println("link was closed") break } log.Println(message) } } // 响应服务端的心跳检测 func TcpClientHB() { // tcp服务端地址 serverAddress := "127.0.0.1:5678" // IPv6 4 // A. 建立连接 conn, err := net.DialTimeout(tcp, serverAddress, time.Second) if err != nil { log.Println(err) return } // 保证关闭 defer conn.Close() log.Printf("connection is establish, client addr is %s\n", conn.LocalAddr()) wg := sync.WaitGroup{} // 接收端 wg.Add(1) go CliReadPing(conn, &wg) wg.Wait() } // 传递的消息类型 type MessageHB struct { ID uint `json:"id,omitempty"` Code string `json:"code,omitempty"` Content string `json:"content,omitempty"` Time time.Time `json:"time,omitempty"` } func CliReadPing(conn net.Conn, wg *sync.WaitGroup) { defer wg.Done() // 传递的消息类型 message := MessageHB{} for { // GOB解码 decoder := gob.NewDecoder(conn) // 解码操作,从conn中读取内容,成功会将解码后的结果,赋值到message变量 err := decoder.Decode(&message) // 错误 io.EOF 时,表示连接被给关闭 if err != nil && errors.Is(err, io.EOF) { log.Println(err) break } // 判断是为为 ping 类型消息 if message.Code == "PING-SERVER" { log.Println("receive ping from", conn.RemoteAddr()) CliWritePong(conn, message) } } } func CliWritePong(conn net.Conn, pingMsg MessageHB) { pongMsg := MessageHB{ ID: uint(rand.Int()), Code: "PONG-CLIENT", Content: fmt.Sprintf("pingID:%d", pingMsg.ID), Time: time.Now(), } // GOB, 二进制编码 // 创建编码器 encoder := gob.NewEncoder(conn) // 利用编码器进行编码 // encode 成功后,会写入到conn,已经完成了conn.Write() if err := encoder.Encode(pongMsg); err != nil { log.Println(err) return } log.Println("pong was send to", conn.RemoteAddr()) return } // 连接池使用 func TcpClientPool() { // tcp服务端地址 serverAddress := "127.0.0.1:5678" // IPv6 4 // A,建立连接池 pool, err := NewTcpPool(serverAddress, PoolConfig{ Factory: &TcpConnFactory{}, InitConnNum: 4, }) if err != nil { log.Fatalln(err) } log.Println(pool, len(pool.idleList)) wg := sync.WaitGroup{} clientNum := 50 wg.Add(clientNum) // B, 复用连接池中的连接 for i := 0; i < clientNum; i++ { // goroutine 模拟独立的客户端 go func(wg *sync.WaitGroup) { defer wg.Done() // 获取连接 conn, err := pool.Get() if err != nil { log.Println(err) return } //log.Println(conn) // 回收连接 pool.Put(conn) }(&wg) } wg.Wait() }