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.

599 lines
13 KiB

2 years ago
package netProgram
import (
2 years ago
"bytes"
"context"
"encoding/gob"
"encoding/json"
"errors"
"io"
2 years ago
"log"
2 years ago
"math/rand"
2 years ago
"net"
2 years ago
"sync"
2 years ago
"time"
)
const tcp = "tcp"
// 服务端
func TcpServer() {
// A. 基于某个地址建立监听
// 服务端地址
//address := "127.0.0.1:5678"
// 端口省略,会使用随机端口
//address := "127.0.0.1:"
// IP省略使用服务器全部的可用IP
// tcp协议类型
//address := "127.0.0.1:5678" // IPv4
//address := "[::1]:5678" // IPv6
address := ":5678" // Any IP or version
listener, err := net.Listen(tcp, address)
if err != nil {
log.Fatalln(err)
}
// 关闭监听
defer listener.Close()
log.Printf("%s server is listening on %s\n", tcp, listener.Addr())
// B. 接受连接请求
// 循环接受
for {
// 阻塞接受
conn, err := listener.Accept()
if err != nil {
log.Println(err)
}
// 处理连接,读写
// 日志连接的远程地址client addr
log.Printf("accept from %s\n", conn.RemoteAddr())
}
}
2 years ago
// 基本读写操作
func TcpServerRW() {
// A. 基于某个地址建立监听
// 服务端地址
address := ":5678" // Any IP or version
listener, err := net.Listen(tcp, address)
if err != nil {
log.Fatalln(err)
}
// 关闭监听
defer listener.Close()
log.Printf("%s server is listening on %s\n", tcp, listener.Addr())
// B. 接受连接请求
// 循环接受
for {
// 阻塞接受
conn, err := listener.Accept()
if err != nil {
log.Println(err)
}
// 处理连接,读写
go HandleConn(conn)
}
}
2 years ago
// 服务端
func TcpBacklogServer() {
// A. 基于某个地址建立监听
// 服务端地址
address := ":5678" // Any IP or version
listener, err := net.Listen(tcp, address)
if err != nil {
log.Fatalln(err)
}
// 关闭监听
defer listener.Close()
log.Printf("%s server is listening on %s\n", tcp, listener.Addr())
// B. 接受连接请求
// 循环接受
for {
// 阻塞接受
conn, err := listener.Accept()
if err != nil {
log.Println(err)
}
// 处理连接,读写
go func(conn net.Conn) {
// 日志连接的远程地址client addr
log.Printf("accept from %s\n", conn.RemoteAddr())
time.Sleep(time.Second)
}(conn)
}
}
2 years ago
// 处理每个连接
func HandleConn(conn net.Conn) {
// 日志连接的远程地址client addr
log.Printf("accept from %s\n", conn.RemoteAddr())
// A.保证连接关闭
defer conn.Close()
// B.向客户端发送数据SerWrite
wn, err := conn.Write([]byte("send some data from server" + "\n"))
if err != nil {
log.Println(err)
}
log.Printf("server write len is %d\n", wn)
// C.从客户端接收数据SerRead
buf := make([]byte, 1024)
rn, err := conn.Read(buf)
if err != nil {
log.Println(err)
}
log.Println("received from client data is:", string(buf[:rn]))
}
// 基本读写操作
func TcpW() {
// A. 基于某个地址建立监听
// 服务端地址
address := ":5678" // Any IP or version
listener, err := net.Listen(tcp, address)
if err != nil {
log.Fatalln(err)
}
// 关闭监听
defer listener.Close()
log.Printf("%s server is listening on %s\n", tcp, listener.Addr())
// B. 接受连接请求
// 循环接受
for {
// 阻塞接受
conn, err := listener.Accept()
if err != nil {
log.Println(err)
}
// 处理连接,读写
go HandleConnW(conn)
}
}
// 处理每个连接
func HandleConnW(conn net.Conn) {
// 日志连接的远程地址client addr
log.Printf("accept from %s\n", conn.RemoteAddr())
// A.保证连接关闭
defer conn.Close()
// 1. 严谨的判断是否写入成功
//data := []byte("send some data from server" + "\n")
//wn, err := conn.SerWrite(data)
//if err != nil {
// log.Println(err)
//}
//// 若要严谨的判断是否写入成功,需要:
//if err == nil && wn == len(data) {
// log.Println("write success")
//}
//log.Printf("server write len is %d\n", wn)
// 2. 写操作会被阻塞
//for i := 0; i < 300000; i++ {
// data := []byte("send some data from server" + "\n")
// wn, err := conn.SerWrite(data)
// if err != nil {
// log.Fatalln(err)
// }
// log.Printf("%d, server write len is %d\n", i, wn)
//}
// 不执行任何写操作
//time.Sleep(5 * time.Second)
// 写入一次
data := []byte("send some data from server" + "\n")
wn, err := conn.Write(data)
if err != nil {
log.Println(err)
}
// 若要严谨的判断是否写入成功,需要:
if err == nil && wn == len(data) {
log.Println("write success")
}
log.Printf("server write len is %d\n", wn)
}
// 并发的读和写操作,全双工
func TcpServerRWConcurrency() {
// A. 基于某个地址建立监听
// 服务端地址
address := ":5678" // Any IP or version
listener, err := net.Listen(tcp, address)
if err != nil {
log.Fatalln(err)
}
// 关闭监听
defer listener.Close()
log.Printf("%s server is listening on %s\n", tcp, listener.Addr())
// B. 接受连接请求
// 循环接受
for {
// 阻塞接受
conn, err := listener.Accept()
if err != nil {
log.Println(err)
}
// 处理连接,读写
go HandleConnConcurrency(conn)
}
}
// 处理每个连接
func HandleConnConcurrency(conn net.Conn) {
// 日志连接的远程地址client addr
log.Printf("accept from %s\n", conn.RemoteAddr())
// A.保证连接关闭
defer conn.Close()
wg := sync.WaitGroup{}
// 并发的写
wg.Add(1)
go SerWrite(conn, &wg, "abcd")
wg.Add(1)
go SerWrite(conn, &wg, "efgh")
wg.Add(1)
go SerWrite(conn, &wg, "ijkl")
// 并发的读
wg.Add(1)
go SerRead(conn, &wg)
wg.Wait()
}
func SerWrite(conn net.Conn, wg *sync.WaitGroup, data string) {
defer wg.Done()
// B.向客户端发送数据SerWrite
for {
wn, err := conn.Write([]byte(data + "\n"))
if err != nil {
log.Println(err)
}
log.Printf("server write len is %d\n", wn)
time.Sleep(1 * time.Second)
}
}
func SerRead(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 client data is:", string(buf[:rn]))
}
}
// 格式化传输
func TcpServerFormat() {
// A. 基于某个地址建立监听
// 服务端地址
address := ":5678" // Any IP or version
listener, err := net.Listen(tcp, address)
if err != nil {
log.Fatalln(err)
}
// 关闭监听
defer listener.Close()
log.Printf("%s server is listening on %s\n", tcp, listener.Addr())
// B. 接受连接请求
// 循环接受
for {
// 阻塞接受
conn, err := listener.Accept()
if err != nil {
log.Println(err)
}
// 处理连接,读写
go HandleConnFormat(conn)
}
}
func HandleConnFormat(conn net.Conn) {
// 日志连接的远程地址client addr
log.Printf("accept from %s\n", conn.RemoteAddr())
// A.保证连接关闭
defer conn.Close()
wg := sync.WaitGroup{}
wg.Add(1)
// 发送端,
go SerWriteFormat(conn, &wg)
wg.Wait()
}
func SerWriteFormat(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{
ID: uint(rand.Int()),
Code: "SERVER-STANDARD",
Content: "message from server",
}
// 编码后数据的展示
var buf bytes.Buffer
encoderData := json.NewEncoder(&buf)
//encoderData := gob.NewEncoder(&buf)
if err := encoderData.Encode(message); err != nil {
log.Println(err)
continue
}
log.Println(buf.String())
// 1, JSON, 文本编码
//// 创建编码器
//encoder := json.NewEncoder(conn)
//// 利用编码器进行编码
//// encode 成功后会写入到conn已经完成了conn.Write()
//if err := encoder.Encode(message); err != nil {
// log.Println(err)
// continue
//}
//log.Println("message was send")
// 2, GOB, 二进制编码
// 创建编码器
encoder := gob.NewEncoder(conn)
// 利用编码器进行编码
// encode 成功后会写入到conn已经完成了conn.Write()
if err := encoder.Encode(message); err != nil {
log.Println(err)
continue
}
log.Println("message was send")
time.Sleep(1 * time.Second)
}
}
// 短连接编程示例
func TcpServerSort() {
// A. 基于某个地址建立监听
// 服务端地址
address := ":5678" // Any IP or version
listener, err := net.Listen(tcp, address)
if err != nil {
log.Fatalln(err)
}
// 关闭监听
defer listener.Close()
log.Printf("%s server is listening on %s\n", tcp, listener.Addr())
// B. 接受连接请求
// 循环接受
for {
// 阻塞接受
conn, err := listener.Accept()
if err != nil {
log.Println(err)
}
// 处理连接,读写
go HandleConnSort(conn)
}
}
func HandleConnSort(conn net.Conn) {
// 日志连接的远程地址client addr
log.Printf("accept from %s\n", conn.RemoteAddr())
// A.保证连接关闭
defer conn.Close()
wg := sync.WaitGroup{}
wg.Add(1)
// 发送端,
go SerWriteSort(conn, &wg)
wg.Wait()
}
func SerWriteSort(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{
ID: uint(rand.Int()),
Code: "SERVER-STANDARD",
Content: "message from server",
}
// GOB, 二进制编码
// 创建编码器
encoder := gob.NewEncoder(conn)
// 利用编码器进行编码
// encode 成功后会写入到conn已经完成了conn.Write()
if err := encoder.Encode(message); err != nil {
log.Println(err)
return
}
log.Println("message was send")
log.Println("link will be close")
return
}
// 心跳检测
func TcpServerHB() {
// A. 基于某个地址建立监听
// 服务端地址
address := ":5678" // Any IP or version
listener, err := net.Listen(tcp, address)
if err != nil {
log.Fatalln(err)
}
// 关闭监听
defer listener.Close()
log.Printf("%s server is listening on %s\n", tcp, listener.Addr())
// B. 接受连接请求
// 循环接受
for {
// 阻塞接受
conn, err := listener.Accept()
if err != nil {
log.Println(err)
}
// 处理连接,读写
go HandleConnHB(conn)
}
}
func HandleConnHB(conn net.Conn) {
// 日志连接的远程地址client addr
log.Printf("accept from %s\n", conn.RemoteAddr())
// A.保证连接关闭
defer func() {
conn.Close()
log.Println("connection be closed")
}()
wg := sync.WaitGroup{}
// 独立的goroutine在连接建立后周期发送ping
wg.Add(1)
// 发送ping
go SerPing(conn, &wg)
wg.Wait()
}
func SerPing(conn net.Conn, wg *sync.WaitGroup) {
defer wg.Done()
// 启动接收pong
ctx, cancel := context.WithCancel(context.Background())
go SerReadPong(conn, ctx)
// ping失败的次数
const maxPingNum = 3
pingErrCounter := 0
//周期性的发送
//利用 time.Ticker
ticker := time.NewTicker(2 * time.Second)
for t := range ticker.C {
pingMsg := MessageHB{
ID: uint(rand.Int()),
Code: "PING-SERVER",
Time: t,
}
// GOB, 二进制编码
encoder := gob.NewEncoder(conn)
// encode 成功后会写入到conn已经完成了conn.Write()
if err := encoder.Encode(pingMsg); err != nil {
log.Println(err)
// 连接有问题的情况
// 累加错误计数器
pingErrCounter++
// 判断是否到达上限
if pingErrCounter == maxPingNum {
// 心跳失败
// 终止pong的处理
cancel()
return
}
}
log.Printf("ping send to %s, ping id is %d\n", conn.RemoteAddr(), pingMsg.ID)
}
}
func SerReadPong(conn net.Conn, ctx context.Context) {
for {
// 处理Ping结束
select {
case <-ctx.Done():
return
default:
message := MessageHB{}
// 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
}
// 判断是为为 pong 类型消息
if message.Code == "PONG-CLIENT" {
log.Printf("receive pong from %s, %s\n", conn.RemoteAddr(), message.Content)
}
}
}
}
// 测试连接池服务端
func TcpServerPool() {
// A. 基于某个地址建立监听
// 服务端地址
address := ":5678" // Any IP or version
listener, err := net.Listen(tcp, address)
if err != nil {
log.Fatalln(err)
}
// 关闭监听
defer listener.Close()
log.Printf("%s server is listening on %s\n", tcp, listener.Addr())
// B. 接受连接请求
// 循环接受
for {
// 阻塞接受
conn, err := listener.Accept()
if err != nil {
log.Println(err)
}
// 处理连接,读写
go HandleConnPool(conn)
}
}
func HandleConnPool(conn net.Conn) {
// 日志连接的远程地址client addr
log.Printf("accept from %s\n", conn.RemoteAddr())
// A.保证连接关闭
defer func() {
conn.Close()
log.Println("connection be closed")
}()
select {}
}