You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

454 lines
9.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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