物流公司网站制作模板,wordpress七牛云设置,淘宝店网站建设规划书,永州市网站建设目录
一、什么是socket#xff1f;
二、Golang中使用TCP
TCP服务端
TCP客户端
三、TCP黏包#xff0c;拆包
1.什么是粘包#xff0c;拆包#xff1f;
2.为什么UDP没有粘包#xff0c;拆包#xff1f;
3.粘包拆包发生场景
4.TCP黏包
黏包服务端
…目录
一、什么是socket
二、Golang中使用TCP
TCP服务端
TCP客户端
三、TCP黏包拆包
1.什么是粘包拆包
2.为什么UDP没有粘包拆包
3.粘包拆包发生场景
4.TCP黏包
黏包服务端
黏包客户端
为什么会出现粘包
解决方案
自定义协议
服务端
客户端
5.TCP拆包
为什么会出现TCP拆包
常见方案
四、Golang中使用UDP
UDP服务端
UDP客户端 一、什么是socket
Socket是BSD UNIX的进程通信机制通常也称作”套接字”用于描述IP地址和端口是一个通信链的句柄。Socket可以理解为TCP/IP网络的API它定义了许多函数或例程程序员可以用它们来开发TCP/IP网络上的应用程序。电脑上运行的应用程序通常通过”套接字”向网络发出请求或者应答网络请求。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层。在设计模式中Socket其实就是一个门面模式它把复杂的TCP/IP协议族隐藏在Socket后面对用户来说只需要调用Socket规定的相关函数让Socket去组织符合指定的协议数据然后进行通信。
网络编程即socket编程 二、Golang中使用TCP
在Go语言中使用Socket编程通常指的是使用标准库net包中的net.TCPConn或net.UDPConn接口来实现TCP或UDP网络通信。以下分别给出一个简单的TCP服务器和客户端示例
TCP服务端
package mainimport (bufiofmtlognet
)func handleConnection(conn net.Conn) {defer conn.Close() // 关闭连接for {reader : bufio.NewReader(conn)var buf [128]byten, err : reader.Read(buf[:]) // 读取数据if err ! nil {fmt.Println(read from client failed, err:, err)break}recvStr : string(buf[:n])fmt.Println(收到client端发来的数据, recvStr)conn.Write([]byte(recvStr)) // 发送数据}
}func main() {listener, err : net.Listen(tcp, :8080)if err ! nil {log.Fatal(err)}defer listener.Close()log.Println(Listening for connections on :8080...)for {conn, err : listener.Accept()if err ! nil {log.Println(Error accepting connection:, err)continue}go handleConnection(conn) // 在新的goroutine中处理每个连接}
}TCP客户端
package mainimport (bufiofmtlognetosstrings
)func main() {conn, err : net.Dial(tcp, localhost:8080)if err ! nil {log.Fatal(err)}defer conn.Close()log.Println(Connected to localhost:8080)inputReader : bufio.NewReader(os.Stdin)for {input, _ : inputReader.ReadString(\n) // 读取用户输入inputInfo : strings.Trim(input, \r\n)if strings.ToUpper(inputInfo) Q { // 如果输入q就退出return}_, err conn.Write([]byte(inputInfo)) // 发送数据if err ! nil {return}buf : [512]byte{}n, err : conn.Read(buf[:])if err ! nil {fmt.Println(recv failed, err:, err)return}fmt.Printf(recv server msg: %s, buf[:n])}
}以上示例展示了如何使用Go语言创建一个简单的TCP服务器和客户端。服务器监听8080端口接受客户端连接并转发数据。客户端连接到本地的8080端口发送一个消息并接收服务器的响应。
对于UDP编程可以使用net.ListenUDP创建UDP监听器net.DialUDP创建UDP连接以及net.UDPConn接口进行数据收发。具体的代码实现与上述TCP示例类似但需要注意UDP是无连接的、不可靠的传输协议相应的编程模型和错误处理会有所不同。 三、TCP黏包拆包
1.什么是粘包拆包
TCP的粘包和拆包问题往往出现在基于TCP协议的通讯中比如RPC框架。在使用TCP进行数据传输时由于TCP是基于字节流的协议而不是基于消息的协议可能会出现粘包多个消息粘在一起和拆包一个消息被拆分成多个部分的问题。这些问题可能会导致数据解析错误或数据不完整。
2.为什么UDP没有粘包拆包
UDPUser Datagram Protocol没有粘包和拆包现象这是由其设计特性和工作方式所决定的。以下是详细解释 面向数据报的传输方式 UDP是一种面向数据报的协议每个数据报datagram都是一个独立、完整的信息单元具有明确的边界。每个数据报包含源端口、目的端口、长度、校验和等信息以及用户数据。发送端将数据封装成一个个数据报发送接收端则按数据报的完整单位接收不存在数据报之间的合并或拆分。 无连接状态 UDP是无连接的协议发送数据前无需建立连接发送后也不维持连接状态。每个数据报的发送与接收都是独立的事件没有前后关联。因此不存在因连接状态导致的数据包合并即“粘包”。 无顺序保证、重传机制 UDP不保证数据报的顺序传递也不进行数据重传。每个数据报在网络中独立传输可能因为网络条件等因素导致乱序、丢失或重复但这些都由应用层自行处理。由于每个数据报都是单独处理的不会因为等待其他数据报而被“粘”在一起也不会因为重传而“拆包”。 固定报头长度 UDP数据报的报头长度是固定的8字节没有可变长度的选项字段这使得接收端可以很容易地定位到用户数据的起始位置无需担心因为解析报头时遇到“粘包”问题。 无流控和拥塞控制 TCP具有滑动窗口、流量控制和拥塞控制机制这些机制可能导致发送端积攒多个小数据包合并成一个大的TCP段发送或者在接收端因窗口大小限制而暂时缓存数据从而形成“粘包”。而UDP没有这些复杂的控制机制数据报一旦发送出去就不受发送端或接收端的流量控制和拥塞控制影响不会发生“粘包”或“拆包”。
综上所述由于UDP的面向数据报、无连接状态、无顺序保证、无重传、固定报头长度以及无流控和拥塞控制等特性每个UDP数据报在发送和接收时都是独立处理的具有明确的边界不会与其他数据报合并“粘包”或需要拆分“拆包”。应用程序使用UDP时需要自行处理数据完整性、顺序和重传等问题。
3.粘包拆包发生场景
因为TCP是面向流没有边界而操作系统在发送TCP数据时会通过缓冲区来进行优化例如缓冲区为1024个字节大小。
如果一次请求发送的数据量比较小没达到缓冲区大小TCP则会将多个请求合并为同一个请求进行发送这就形成了粘包问题。如果一次请求发送的数据量比较大超过了缓冲区大小TCP就会将其拆分为多次发送这就是拆包。
关于粘包和拆包可以参考下图的几种情况
理想状况两个数据包逐一分开发送。粘包两个包一同发送。拆包Server接收到不完整的或多出一部分的数据包。
4.TCP黏包
黏包服务端
package mainimport (bufiofmtionet
)// socket_stick/server/main.gofunc process(conn net.Conn) {defer conn.Close()reader : bufio.NewReader(conn)var buf [1024]bytefor {n, err : reader.Read(buf[:])if err io.EOF {break}if err ! nil {fmt.Println(read from client failed, err:, err)break}recvStr : string(buf[:n])fmt.Println(收到client发来的数据, recvStr)}
}func main() {listen, err : net.Listen(tcp, 127.0.0.1:8080)if err ! nil {fmt.Println(listen failed, err:, err)return}defer listen.Close()for {conn, err : listen.Accept()if err ! nil {fmt.Println(accept failed, err:, err)continue}go process(conn)}
}黏包客户端
package mainimport (fmtnet
)// socket_stick/client/main.gofunc main() {conn, err : net.Dial(tcp, 127.0.0.1:8080)if err ! nil {fmt.Println(dial failed, err, err)return}defer conn.Close()for i : 0; i 10; i {msg : 你好吃了吗conn.Write([]byte(msg))}
}客户端分10次发送的数据在服务端并没有成功的输出10次而是多条数据“粘”到了一起。
为什么会出现粘包
主要原因就是tcp数据传递模式是流模式在保持长连接的时候可以进行多次的收和发。
“粘包可发生在发送端也可发生在接收端
由Nagle算法造成的发送端的粘包Nagle算法是一种改善网络传输效率的算法。简单来说就是当我们提交一段数据给TCP发送时TCP并不立刻发送此段数据而是等待一小段时间看看在等待期间是否还有要发送的数据若有则会一次把这两段数据发送出去。接收端接收不及时造成的接收端粘包TCP会把接收到的数据存在自己的缓冲区中然后通知应用层取数据。当应用层由于某些原因不能及时的把TCP的数据取出来就会造成TCP缓冲区中存放了几段数据。
出现粘包的关键在于接收方不确定将要传输的数据包的大小因此我们可以对数据包进行封包和拆包的操作。
封包封包就是给一段数据加上包头这样一来数据包就分为包头和包体两部分内容了(过滤非法包时封包会加入包尾内容)。包头部分的长度是固定的并且它存储了包体的长度根据包头长度固定以及包头中含有包体长度的变量就能正确的拆分出一个完整的数据包。
我们可以自己定义一个协议比如数据包的前4个字节为包头里面存储的是发送的数据的长度。
解决方案
自定义协议
package protoimport (bufiobytesencoding/binary
)// Encode 将消息编码
func Encode(message string) ([]byte, error) {// 读取消息的长度转换成int32类型占4个字节var length int32(len(message))var pkg new(bytes.Buffer)// 写入消息头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}return pkg.Bytes(), nil
}// Decode 解码消息
func Decode(reader *bufio.Reader) (string, error) {// 读取消息的长度lengthByte, _ : reader.Peek(4) // 读取前4个字节的数据lengthBuff : bytes.NewBuffer(lengthByte)var length int32err : binary.Read(lengthBuff, binary.LittleEndian, length)if err ! nil {return , err}// Buffered返回缓冲中现有的可读取的字节数。if int32(reader.Buffered()) length4 {return , err}// 读取真正的消息数据pack : make([]byte, int(4length))_, err reader.Read(pack)if err ! nil {return , err}return string(pack[4:]), nil
}服务端
package mainimport (bufiocsdn/protofmtionet
)func process(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 msg failed, err:, err)return}fmt.Println(收到client发来的数据, msg)}
}func main() {listen, err : net.Listen(tcp, 127.0.0.1:8080)if err ! nil {fmt.Println(listen failed, err:, err)return}defer listen.Close()for {conn, err : listen.Accept()if err ! nil {fmt.Println(accept failed, err:, err)continue}go process(conn)}
}客户端
package mainimport (csdn/protofmtnet
)func main() {conn, err : net.Dial(tcp, 127.0.0.1:8080)if err ! nil {fmt.Println(dial failed, err, err)return}defer conn.Close()for i : 0; i 10; i {msg : 你好吃了吗data, err : proto.Encode(msg)if err ! nil {fmt.Println(encode msg failed, err:, err)return}conn.Write(data)}
}5.TCP拆包
为什么会出现TCP拆包
TCP拆包现象主要由以下几个原因导致 网络传输限制 - 最大传输单元MTUTCP协议允许发送端将数据划分为多个数据段segments进行发送。这些数据段在传输过程中可能会遇到网络路径中不同设备的最大传输单元MTU限制。MTU是指网络层如IP层能够承载的最大数据包尺寸通常以字节为单位。如果一个TCP数据段的大小超过了路径中某个设备的MTU该设备会将数据包进行分片fragmentation将其分割成多个较小的数据包以便通过网络。这些分片数据包可能独立地经过网络传输并在接收端以不同的顺序到达。尽管TCP协议会确保这些分片数据包在接收端按正确的顺序重组但应用层接收到的数据可能不再是发送端最初连续发送的形式从而表现为拆包。 接收端缓冲区满接收端的TCP连接有一个缓冲区用于暂存接收到的数据。当接收端处理数据的速度赶不上数据到达的速度或者由于其他原因导致缓冲区空间不足时新的数据段可能会被推迟接收。这种情况下即使原本连续的数据段在传输过程中没有被网络设备分片也可能因为接收端暂时无法接纳而被迫分开接收从而在应用层看起来像是发生了拆包。 网络拥塞在网络拥塞时数据包可能会在网络中经历更长的延迟甚至被路由器暂时存储队列化。这可能导致原本连续发送的数据段到达接收端的顺序被打乱或者由于接收端TCP窗口大小限制只能接收部分数据从而出现拆包现象。
综上所述TCP拆包主要源于网络传输中的MTU限制导致的数据分片、接收端缓冲区处理能力的限制以及网络拥塞等因素。为应对拆包问题通常需要在应用层设计合适的协议或策略如消息定界、使用更高层协议、合理设置接收缓冲区大小、实现应用层重传机制等。
常见方案
固定长度发送端将每个消息固定为相同的长度接收端按照固定长度进行拆包。这样可以确保每个消息的长度是一致的但是对于不同长度的消息可能会浪费一些空间。分隔符发送端在每个消息的末尾添加一个特殊的分隔符比如换行符或特殊字符接收端根据分隔符进行拆包。这种方法适用于消息中不会出现分隔符的情况。消息长度前缀发送端在每个消息前面添加一个固定长度的消息长度字段接收端先读取消息长度字段然后根据长度读取相应长度的数据。这种方法可以准确地拆分消息但需要保证消息长度字段的一致性。
四、Golang中使用UDP
在Go语言中使用UDPUser Datagram Protocol进行网络通信您可以使用标准库net包提供的net.UDPConn接口。以下是一个简单的UDP服务器和客户端示例
UDP服务端
package mainimport (fmtnet
)func main() {// 监听指定的UDP端口serverAddr, err : net.ResolveUDPAddr(udp, :8080)if err ! nil {fmt.Println(Error resolving address:, err)return}listener, err : net.ListenUDP(udp, serverAddr)if err ! nil {fmt.Println(Error listening:, err)return}defer listener.Close()fmt.Println(UDP server listening on :8080)buf : make([]byte, 1024)for {n, remoteAddr, err : listener.ReadFromUDP(buf)if err ! nil {fmt.Println(Error reading:, err)continue}message : buf[:n]fmt.Printf(Received message from %v: %s\n, remoteAddr, message)// 处理消息并回复可选response : Hello, UDP client!_, err listener.WriteToUDP([]byte(response), remoteAddr)if err ! nil {fmt.Println(Error writing:, err)}}
}
UDP客户端
package mainimport (fmtnet
)func main() {serverAddr, err : net.ResolveUDPAddr(udp, localhost:8080)if err ! nil {fmt.Println(Error resolving address:, err)return}conn, err : net.DialUDP(udp, nil, serverAddr)if err ! nil {fmt.Println(Error connecting:, err)return}defer conn.Close()message : Hello, UDP server!_, err conn.Write([]byte(message))if err ! nil {fmt.Println(Error sending:, err)return}fmt.Println(Sent message:, message)buf : make([]byte, 1024)n, _, err : conn.ReadFromUDP(buf)if err ! nil {fmt.Println(Error reading:, err)return}response : buf[:n]fmt.Printf(Received response: %s\n, response)
}
在这个示例中服务器监听8080端口接收客户端发送的消息并打印出来然后向客户端发送一条回复消息。客户端连接到服务器发送一条消息并接收服务器的响应。注意UDP是无连接的、不可靠的协议不保证消息的顺序、可靠传输或重传适用于对实时性要求较高但能容忍一定程度数据丢失的应用场景。在实际使用时可能需要根据应用需求添加适当的错误处理、重传机制和数据校验等逻辑。 文章转载自: http://www.morning.pbmg.cn.gov.cn.pbmg.cn http://www.morning.dmwck.cn.gov.cn.dmwck.cn http://www.morning.mdtfh.cn.gov.cn.mdtfh.cn http://www.morning.qyhcg.cn.gov.cn.qyhcg.cn http://www.morning.qhmql.cn.gov.cn.qhmql.cn http://www.morning.ayftwl.cn.gov.cn.ayftwl.cn http://www.morning.yjmns.cn.gov.cn.yjmns.cn http://www.morning.lnfkd.cn.gov.cn.lnfkd.cn http://www.morning.qjsxf.cn.gov.cn.qjsxf.cn http://www.morning.gmdtk.cn.gov.cn.gmdtk.cn http://www.morning.ymfzd.cn.gov.cn.ymfzd.cn http://www.morning.nqbcj.cn.gov.cn.nqbcj.cn http://www.morning.snrhg.cn.gov.cn.snrhg.cn http://www.morning.cbqqz.cn.gov.cn.cbqqz.cn http://www.morning.kqcqr.cn.gov.cn.kqcqr.cn http://www.morning.rnyhx.cn.gov.cn.rnyhx.cn http://www.morning.ttvtv.cn.gov.cn.ttvtv.cn http://www.morning.kflzy.cn.gov.cn.kflzy.cn http://www.morning.dmwjl.cn.gov.cn.dmwjl.cn http://www.morning.bklhx.cn.gov.cn.bklhx.cn http://www.morning.ngzkt.cn.gov.cn.ngzkt.cn http://www.morning.ykrss.cn.gov.cn.ykrss.cn http://www.morning.pgmyn.cn.gov.cn.pgmyn.cn http://www.morning.lbpfl.cn.gov.cn.lbpfl.cn http://www.morning.tygn.cn.gov.cn.tygn.cn http://www.morning.ymwcs.cn.gov.cn.ymwcs.cn http://www.morning.gpnwq.cn.gov.cn.gpnwq.cn http://www.morning.sbrpz.cn.gov.cn.sbrpz.cn http://www.morning.sgmis.com.gov.cn.sgmis.com http://www.morning.knsmh.cn.gov.cn.knsmh.cn http://www.morning.mxbks.cn.gov.cn.mxbks.cn http://www.morning.jxcwn.cn.gov.cn.jxcwn.cn http://www.morning.xfdkh.cn.gov.cn.xfdkh.cn http://www.morning.rycd.cn.gov.cn.rycd.cn http://www.morning.qbdqc.cn.gov.cn.qbdqc.cn http://www.morning.brwei.com.gov.cn.brwei.com http://www.morning.bpmtx.cn.gov.cn.bpmtx.cn http://www.morning.wjlhp.cn.gov.cn.wjlhp.cn http://www.morning.dywgl.cn.gov.cn.dywgl.cn http://www.morning.yyzgl.cn.gov.cn.yyzgl.cn http://www.morning.gwkwt.cn.gov.cn.gwkwt.cn http://www.morning.xzrbd.cn.gov.cn.xzrbd.cn http://www.morning.jqmmf.cn.gov.cn.jqmmf.cn http://www.morning.lszjq.cn.gov.cn.lszjq.cn http://www.morning.lpppg.cn.gov.cn.lpppg.cn http://www.morning.prmyx.cn.gov.cn.prmyx.cn http://www.morning.lqrpk.cn.gov.cn.lqrpk.cn http://www.morning.dblfl.cn.gov.cn.dblfl.cn http://www.morning.rmppf.cn.gov.cn.rmppf.cn http://www.morning.qxgmp.cn.gov.cn.qxgmp.cn http://www.morning.qnkqk.cn.gov.cn.qnkqk.cn http://www.morning.ngjpt.cn.gov.cn.ngjpt.cn http://www.morning.tsxg.cn.gov.cn.tsxg.cn http://www.morning.ksqyj.cn.gov.cn.ksqyj.cn http://www.morning.tpfny.cn.gov.cn.tpfny.cn http://www.morning.hlmkx.cn.gov.cn.hlmkx.cn http://www.morning.srbmc.cn.gov.cn.srbmc.cn http://www.morning.ldwxj.cn.gov.cn.ldwxj.cn http://www.morning.bwgrd.cn.gov.cn.bwgrd.cn http://www.morning.wrkcw.cn.gov.cn.wrkcw.cn http://www.morning.syfty.cn.gov.cn.syfty.cn http://www.morning.njqpg.cn.gov.cn.njqpg.cn http://www.morning.gtkyr.cn.gov.cn.gtkyr.cn http://www.morning.dtlnz.cn.gov.cn.dtlnz.cn http://www.morning.yxshp.cn.gov.cn.yxshp.cn http://www.morning.xhwty.cn.gov.cn.xhwty.cn http://www.morning.cwrpd.cn.gov.cn.cwrpd.cn http://www.morning.fqyqm.cn.gov.cn.fqyqm.cn http://www.morning.clkyw.cn.gov.cn.clkyw.cn http://www.morning.zhmgcreativeeducation.cn.gov.cn.zhmgcreativeeducation.cn http://www.morning.cgthq.cn.gov.cn.cgthq.cn http://www.morning.ljfjm.cn.gov.cn.ljfjm.cn http://www.morning.nnrqg.cn.gov.cn.nnrqg.cn http://www.morning.xnrgb.cn.gov.cn.xnrgb.cn http://www.morning.ldhbs.cn.gov.cn.ldhbs.cn http://www.morning.bqpgq.cn.gov.cn.bqpgq.cn http://www.morning.mjytr.cn.gov.cn.mjytr.cn http://www.morning.nmkbl.cn.gov.cn.nmkbl.cn http://www.morning.rxkl.cn.gov.cn.rxkl.cn http://www.morning.nlbw.cn.gov.cn.nlbw.cn