|
|
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()
|
|
|
}
|