标签:流程 包含 解决 listen 反序 多个 粘包 端口绑定 bytes
一、网络编程的目标
编写一个C/S或B/S架构的基于网络通信的软件
C/S架构:客户端---服务端
B/S架构:浏览器----服务端
学习socket编程就是要编写客户端软件和服务端软件,然后实现服务端和客户端基于网络通信
服务端特点:1、不间断地提供服务;2、服务端要支持并发+高性能
二、网络
网络 = 物理连接介质 + 互联网协议
互联网协议分为OSI七层,或TCP/IP五层:
物理层:发送电信号-----基于二进制
数据链路层:ethernet以太网协议-----基于mac地址,在局域网内通信
网络层:IP协议-----基于IP地址
传输层:TCP/UDP协议------基于端口(端口即应用程序与网卡关联的编号)
应用层:HTTP、mail、ftp协议等
IP协议的作用:一个是为每一台计算机分配IP地址,另一个是确定哪些地址在同一个子网络
ARP协议:在同一个局域网内,根据IP地址获取mac地址,操作系统自动转换
路由协议:网关与网关之间的通信
TCP协议:TCP建立的是一个双向连接,也叫流式协议
3次握手,建立客户端和服务端的双向通路
4次挥手,断连接,服务端先发起断连
mac地址 + IP地址 +端口就可以定位到世界上独一无二的应用软件;有了ARP协议,IP地址 + 端口就可以定位到世界上独一无二的应用软件。
三、socket编程
sockct(套接字)是位于应用层和传输层之间的一个抽象层,专门把传输层以下的协议封装成接口给应用层使用。
套接字有两种(或者称为有两个种族),分别是基于文件型的(AF_UNIX)和基于网络型的(AF_INET)。
1、socket工作流程
服务端:
socket()---bind()---listen()---accept()---recv()---send()---close()
服务端先初始化socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。
服务端:
socket()---connect()---send()---recv()---close()
客户端初始化一个socket,然后连接服务器(connect),如果连接成功,这时客户端与服务端的连接就建立了。
客户端发送数据请求(send),服务器端接收请求并处理请求(recv),然后把回应数据发送给客户端(send),客户端读取数据(recv),最后关闭连接(close),一次交互结束。
bind() 绑定IP地址和端口。本地回环地址:127.0.0.1,端口:0到65535,其中0到1024是给系统用的
listen() 括号里面的数字代表同一时间只能进来多少个请求
accept() 等待信息
reav(1024) 代表收消息,1024是一个最大的限制
send() 回消息
close() 关闭连接
2、粘包
只有TCP有粘包现象,UDP永远不会粘包,因为TCP协议是面向流的协议,而UDP是面向消息的协议。
所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。
两种情况下会发生粘包:
1、发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据量很小,会合到一起,产生粘包)
2、接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)
TCP是基于数据流的,于是收发的消息不能为空,这就需要在客户端和服务端都添加空消息的处理机制
粘包的解决方法:
为字节流加上自定义固定长度报头,报头中包含字节流长度,然后一次send到对端,对端在接收时,先从缓存中取出定长的报头,然后再取真实数据
使用struct模块解决粘包
struct模块的作用:
1、把整型数字转成bytes类型
2、转成的bytes是固定长度
可以把报头做成字典,字典里包含将要发送的真实数据的详细信息,然后json序列化,然后用struck将序列化后的数据长度打包成4个字节(4个字节足够用了)
发送时:
先发报头长度
再编码报头内容然后发送
最后发真实内容
接收时:
先收报头长度,用struct取出来
根据取出的长度收取报头内容,然后解码,反序列化
从反序列化的结果中取出待取数据的详细信息,然后去取真实的数据内容
3、基于UDP协议通信的套接字
UDP是基于数据报的,一发对应一收
特点:无连接
优点:发送效率高,但有效传输的数据量最多为512bytes
缺点:不可靠(发送数据无须对方确认,容易丢包)
标签:流程 包含 解决 listen 反序 多个 粘包 端口绑定 bytes
原文地址:https://www.cnblogs.com/Python1/p/8981914.html