socket套接字
socket
1,定义
- 套接字
- 基于tcp协议
- socket是基于应用层与传输层之间的抽象层,是一组操作起来非常简单的接口,接收应用层的数据,然后传给操作系统
- 分类:
- 基于文件类型的套接字家族:AF-UNIX,不常用
- 基于网络类型的套接字家族:AF-INET
- 模块语法
- shell:命令解释器,相当于调用cmd,执行指定的命令
- stdout:正确结果以字符串的形式send个客户端
- stderr:错误的结果以字符串的形式send给客户端
- windows操作系统的默认编码是gbk
粘包
- 粘包的两种方式
- 连续短暂的多次send,数据量很小,数据就会统一发出去
- send的数据过大,大于对方recv的上限时,对方第一次recv时,会接收上一次没有recv完的剩余数据,这就是粘包
- 只有tcp会粘包,udp永远不会粘包,粘包现象的发生于缓冲区有关系
- 缓存区
- 暂时储存一些数据
- 缓存取得存在,避免了网络波动等影响对数据传输的影响,保证了数据的收发稳定,匀速
- 缺点:就是照成了粘包现象
- 解决粘包现象
- 发送数据长度,客服端循环接收数据知道接收完数据
- 自定义报头
ftp协议
1,文件传输协议
- FTP使用两个并行的TCP连接来传输文件,一个是控制连接(用于在两主机之间传递控制信息),一个是数据连接(用于实际传输一个文件)。因为FTP协议使用一个分离的控制连接,所以我们也称FTP的控制信息是带外传送的
- 自定制报头
- 可以解觉文件过大的问题
2,服务端要点
自定义报头
head_dic = {"filename":"文件名",
"md5":11111111111,
"size":total_size}
json形式的报头
head_dic_json = json.dumps(head_dic)
bytes形式报头
head_dic_json_bytes = head_dic_json.encoude('utf-8')
bytes长度
len_head = len(head_dic_json_bytes)
将不固定的int总字节数转换成固定长度的4个字节
head_size = struct.pack('i',len_head)
发送固定字节
conn.send(head_size)
发送字典的bytes数据
conn.send(head_dic_json_size)
发送总数据(result)
3,客户端要点
接收4个固定字节的报头
from_server_data = client.recv(4)
将接收到的4个字节的固定报头翻转会字典的bytes长度
len_dic_size = struct.unpack('i',from_server_data)
通过翻转的长度接收字典的bytes数据
dic_bytes = client.recv(len_dic_size)
将bytes类型装换成json类型的字典
dic_json = dic_bytes.decode('utf-8')
json反序列化成原字典
dic = json.loads(dic_json)
得到原字典就得到了源数据的总字节数
total_size = dic["size"]
udp
-
服务端
- 基于udp协议的socket无序建立管道,先开启服务端或者客户端都行
- 基于udp协议的socket接收一个消息,与发送一个消息都是无连接的
- 只要拿到我都IP地址和端口就可以给我发消息,我按照顺序接收消息
import socket server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 基于网络的UDP协议的socket server.bind(('192.168.14.198',9000)) while 1: from_client_data = server.recvfrom(1024) # 阻塞,等待客户来消息 print(f'\033[1;35;0m来自客户端{from_client_data[1]}: {from_client_data[0].decode("utf-8")} \033[0m') # to_client_data = input('>>>').strip() # server.sendto(to_client_data.encode('utf-8'),from_client_data[1])
2,client端
-
udp
-
import socket client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 基于网络的UDP协议的socket while 1: to_server_data = input('>>>:').strip() client.sendto(to_server_data.encode('utf-8'),('127.0.0.1',9000)) # data,addr = client.recvfrom(1024) # print(f'来自服务端{addr}消息:{data.decode("utf-8")}')
-
希望你眼眸有星辰,心中有山海,从此以梦为马,不负韶华