TCP
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠 的、基于字节流的传输层通信协议。(注:摘自百度百科)
三次握手
四次挥手
客户端主动向服务端发送断开请求,服务器发送消息代表已不再接收客户端消息。
服务端等待传输任务结束后向客户端发送断开请求,客户端响应消息同时服务端我们断开连接,这个时候客户端会进入一个计时等待时间,假如这个时候服务端又发送了一条断开的消息,这个时候就说明之前发送的消息服务器没有收到,客户端就会再次发送断开响应。直到客户端在计时等待的时候没有收到服务端的消息了,那么客户端就可以关闭连接了。
UDP
UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种 无连接 的传输层协议,提供面向事务的简单 不可靠 信息传送服务。(注:摘自百度百科)
TCP
客户端
import socket
soc=socket.socket()
soc.connect(('127.0.0.1',8080))
soc.send('hello hello'.encode())
data=soc.recv(1024)
print('我收到服务端回的',data.decode())
soc.close()
服务端
import socket
soc=socket.socket()
soc.bind(('127.0.0.1',8080))
soc.listen(5)
conn,addr=soc.accept()
data=conn.recv(1024)
print('我收到客户端发的',data.decode())
conn.send(data.decode().upper().encode())
conn.close()
soc.close()
UDP
客户端
import socket
s = socket.socket(type=socket.SOCK_DGRAM)
s.sendto('hello world!'.encode(),('127.0.0.1',8080))
print('收到服务端消息',s.recvfrom(1024)[0].decode())
s.close()
服务端
import socket
s = socket.socket(type=socket.SOCK_DGRAM)
s.bind(('127.0.0.1',8080))
data = s.recvfrom(1024)
print('收到客户端消息', data[0].decode())
s.sendto(data[0].decode().upper().encode(), data[1])
s.close()
只有TCP有粘包现象,UDP永远不会粘包,因为TCP是基于 数据流 的协议,而UDP是基于 数据报 的协议
因为接收方不知道消息与消息之间的界限,不知道一次性接收多少字节的数据所造成的。
模拟UDP的数据报形式
服务端
import socket
import struct
import json
soc = socket.socket()
soc.bind(('127.0.0.1', 8080))
soc.listen(5)
conn, addr = soc.accept()
s_bytes = 'Hello Client!'.encode()
# 创建头字典,将数据长度保存到字典中
dic = {'size': len(s_bytes)}
# 将字典转成bytes格式
dic_bytes = (json.dumps(dic)).encode()
# head_count是4个字节的长度
head_count = struct.pack('i', len(dic_bytes))
# 发送同步信息长度
conn.send(head_count)
# 发送头部内容
conn.send(dic_bytes)
# 发了内容
conn.send(s_bytes)
conn.close()
soc.close()
客户端
import socket
import struct
import json
s = socket.socket()
s.connect(('127.0.0.1', 8080))
# 头部字典长度固定4字节
dic_bytes = s.recv(4)
# 解出头部字典的长度
dic_len = struct.unpack('i', dic_bytes)[0]
# 接收头部字典
str_dic = s.recv(dic_len)
# 将字符串转成字典
dic = json.loads(str_dic)
# 获取数据长度
data_len = dic['size']
# 接收数据部分
while data_len > 0:
if data_len > 1024:
print(s.recv(1024))
else:
print(s.recv(data_len))
data_len -= 1024
s.close()
服务端
import socket
import struct
import json
import socketserver
def read_data(con: socket.socket) -> str:
pack = con.recv(4)
head_size = struct.unpack('i', pack)[0]
head_dic = json.loads(con.recv(head_size).decode()) # type:dict
data_size = head_dic.get('data_size')
data = b''
while data_size > 0:
if data_size > 1024:
data += con.recv(1024)
else:
data += con.recv(data_size)
data_size -= 1024
return data.decode()
def write_data(con: socket.socket, data: str):
data_size = len(data.encode())
data_hred = {'data_size': data_size}
data_hred = json.dumps(data_hred).encode()
con.send(struct.pack('i', len(data_hred)))
con.send(data_hred)
con.send(data.encode())
class myTcp(socketserver.BaseRequestHandler):
def handle(self):
while True:
data = read_data(self.request)
print('收到客户端消息', data)
write_data(self.request, data.upper())
if __name__ == '__main__':
s = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), myTcp)
s.serve_forever()
客户端
import socket
import struct
import json
def read_data(con: socket.socket) -> str:
pack = con.recv(4)
head_size = struct.unpack('i', pack)[0]
head_dic = json.loads(con.recv(head_size).decode()) # type:dict
data_size = head_dic.get('data_size')
data = b''
while data_size > 0:
if data_size > 1024:
data += con.recv(1024)
else:
data += con.recv(data_size)
data_size -= 1024
return data.decode()
def write_data(con: socket.socket, data: str):
data_size = len(data.encode())
data_hred = {'data_size': data_size}
data_hred = json.dumps(data_hred).encode()
con.send(struct.pack('i', len(data_hred)))
con.send(data_hred)
con.send(data.encode())
if __name__ == '__main__':
s = socket.socket()
s.connect(('127.0.0.1', 8080))
while True:
write_data(s, 'hello world!')
print(read_data(s))
原文:https://www.cnblogs.com/Gredae/p/11562021.html