TCP协议-GO语言
2021-03-06 02:29
标签:std protocol 命令 拆分 nil UNC cep else listener 0,server服务端——常规版本 1,client客户端——常规版本 上面 for 循环发送消息,速度快,存在粘包 1,客户端代码——粘包解决版 2,client客户端代码——粘包解决版 TCP协议-GO语言 标签:std protocol 命令 拆分 nil UNC cep else listener 原文地址:https://www.cnblogs.com/shijieziben/p/14307744.htmlpackage main
//server服务端
import (
"fmt"
"net"
)
func main() {
//01,启动服务 net.Listen
listener, err1 := net.Listen("tcp", "127.0.0.1:20000") //net.Listen网络.监听
if err1 != nil {
fmt.Println("12.0.0.1:20000 连接错误!!!")
return
}
//02,监听.接收连接 listener.Accept(),用 for循环建立多个请求
for {
conn, err2 := listener.Accept() //listener.Accept收听.接收
if err2 != nil {
fmt.Println("accept 接受请求错误!!!")
return
}
//03,读取信息 连接对象.Read([]byte存放信息),发送客户端
go conn_(conn)
}
}
//--------------------------使用函数------------------------------
func conn_(conn net.Conn) {
var tmp [128]byte
for {
n, err := conn.Read(tmp[:]) //用for 循环 conn对象可以一直保持接收
if err != nil {
fmt.Println("客户端读取错误!!!!")
return
}
fmt.Println(string(tmp[:n]))
}
}
package main
//client客户端
import (
"fmt"
"net"
//"bufio"
//"os"
//"strings"
)
func main() {
//01,与server端建立连接
conn, err1 := net.Dial("tcp", "127.0.0.1:20000") //net.Dial网络.拨号
if err1 != nil {
fmt.Println("dial 127.0.0.1:20000 failed,err")
return
}
//02,发送数据
//var msg string
/*用法1 用命令行参数os.Args发出
if len(os.Args) 弊端无法过滤空格输出
for {
fmt.Print("请老大发言:")
fmt.Scanln(&msg)
if msg == "exit" {
break
}
conn.Write([]byte(msg))
}*/
/*用法3 用bufio.NewReader()
for {
reader := bufio.NewReader(os.Stdin) //从标准输入生成读对象
fmt.Print("请老大发言:")
text, _ := reader.ReadString(‘\n‘) //读到换行
text = strings.TrimSpace(text) //trim space去除空格
conn.Write([]byte(text))
}*/
for i := 0; i
//出现"粘包"的关键在于接收方不确定数据包大小,可以将数据封包和拆包。
//封包: 封包就是给一段数据加包头,过滤非法包时封包会加入”包尾“内容
//包头长度固定,且储存包体长度,根据包头长度固定和包体长度的变量就能确定拆分出完整数据包
//自己定义一个协议,比如数据包前4个字节为包头,储存的是发送的数据长度
自写一个protocol包,调用里面的 Encode()编码, DEcode()解码
0,粘包方案package proto
import (
"bufio"
"bytes"
"encoding/binary" //编码/二进制
)
//01,先用 binary.Write() 将消息打包成 int32 4个字节,小端排列对象
//02,再用 binary.Read() 将消息按照4字节,小端读取(1次读标准长度来避免粘包)
//Encode 将消息编码
func Encode(message string) ([]byte, error) {
//读取长度,转换成int32类型(占4个字节)
length := int32(len(message))
//定义一个字节类型的缓冲对象,具有Read 和Write 方法的包
pkg := new(bytes.Buffer)
//调用二进制写入函数,把pck包对象,按照传入int32类型的长度,小端方式排列
err := binary.Write(pkg, binary.LittleEndian, length)
if err != nil {
//如果对象不为空,返回空,和对象
return nil, err
}
//小端方式写入类容
err = binary.Write(pkg, binary.LittleEndian, []byte(message))
if err != nil {
return nil, err
}
//把Bytes.Buffer对象 转换成Bytes()对象返回
return pkg.Bytes(), nil
}
//Decode 将消息解码
func Decode(reader *bufio.Reader) (string, error) {
//读取消息长度
lengthByte, _ := reader.Peek(4) //读取4个字节的数据
lengthBuff := bytes.NewBuffer(lengthByte) //创建字节对象
var length int32
//把字节对象按照 小端 读取长度放入length中,然后判断 01返回err是否为空 02类容有长度
err := binary.Read(lengthBuff, binary.LittleEndian, &length)
if err != nil {
return "", err
}
//Buffered返回缓冲中现有的可读取的字节数
if int32(reader.Buffered())
package main
//server服务端
import (
"bufio"
"fmt"
"io"
"net"
)
func main() {
//01,启动服务 net.Listen
listener, err1 := net.Listen("tcp", "127.0.0.1:20000") //net.Listen网络.监听
if err1 != nil {
fmt.Println("12.0.0.1:20000 连接错误!!!")
return
}
//02,接受连接 listener.Accept(),用 for循环建立多个请求
for {
conn, err2 := listener.Accept() //listener.Accept收听.接受
if err2 != nil {
fmt.Println("accept 接受请求错误!!!")
return
}
//03,读取信息 连接对象.Read([]byte存放信息),发送客户端
go conn_(conn)
}
}
//--------------------------使用函数------------------------------
func conn_(conn net.Conn) {
defer conn.Close()
reader := bufio.NewReader(conn)
for {
msg, err := proto.Decode(reader)
if err == io.EOF {
return
}
if err != nil {
fmt.Println("Decode failed,err:", err)
return
}
fmt.Println("收到client发来的消息:", msg)
}
}
package main
//client客户端
import (
"fmt"
"net"
//"bufio"
//"os"
//"strings"
)
func main() {
//01,与server端建立连接
conn, err1 := net.Dial("tcp", "127.0.0.1:20000") //net.Dial网络.拨号
if err1 != nil {
fmt.Println("dial 127.0.0.1:20000 failed,err")
return
}
//02,发送数据
//var msg string
/*用法1 用命令行参数os.Args发出
if len(os.Args) 弊端无法过滤空格输出
for {
fmt.Print("请老大发言:")
fmt.Scanln(&msg)
if msg == "exit" {
break
}
conn.Write([]byte(msg))
}*/
/*用法3 用bufio.NewReader()
for {
reader := bufio.NewReader(os.Stdin) //从标准输入生成读对象
fmt.Print("请老大发言:")
text, _ := reader.ReadString(‘\n‘) //读到换行
text = strings.TrimSpace(text) //trim space去除空格
conn.Write([]byte(text))
}*/
for i := 0; i
Encode
上一篇:JS数组去重
下一篇:python自动化操作问题