tcp协议传输数据存在粘包现象,udp协议不存在粘包协议。python
1.发生在发送端的粘包web
因为两个数据的发送时间间隔短+数据的长度小,因此由tcp协议的优化机制将两条信息做为一条信息发送出去了,是为了减小tcp协议中的“确认收到”的网络延迟时间缓存
2.在接收端的粘包网络
因为tcp协议中所传输的数据无边界,因此来不及接收的多条数据会在接收方的内核的缓存端黏在一块儿并发
3.本质: 接收信息的边界不清晰app
1.自定义协议1:dom
a.首先发送报头异步
报头长度4个字节
内容是 即将发送的报文的字节长度
struct模块socket
b.再发送报文tcp
2.自定义协议2
专门用来作文件发送的协议
1.三次握手
三次握手的过程在代码中是由accept和connect共同完成的,具体的细节再socket中没有体现出来
2.四次挥手
io模型种类:
server端同时与多个client客户端之间的聊天:
socket的非阻塞io模型 + io多路复用实现的
虽然非阻塞,提升了CPU的利用率,可是耗费CPU作了不少无用功
# server.py import socket sk = socket.socket() sk.bind(('127.0.0.1',9000)) sk.setblocking(False) # 非阻塞,setblocking()的参数为False时,表示非阻塞,若是参数不写,默认为True。 sk.listen() conn_l = [] del_l = [] while True: try: conn,addr = sk.accept() # 阻塞,直到有一个客户端来连我 print(conn) conn_l.append(conn) except BlockingIOError: for c in conn_l: try: msg = c.recv(1024).decode('utf-8') if not msg: del_l.append(c) continue print('-->',[msg]) c.send(msg.upper().encode('utf-8')) except BlockingIOError:pass for c in del_l: conn_l.remove(c) del_l.clear() sk.close() # client.py import time import socket sk = socket.socket() sk.connect(('127.0.0.1',9000)) for i in range(30): sk.send(b'zhangsan') msg = sk.recv(1024) print(msg) time.sleep(0.2) sk.close()
socketserver模块解决了socket的阻塞问题,直接实现tcp协议可并发的server端
# server.py import socketserver class Myserver(socketserver.BaseRequestHandler): def handle(self): # 自动触发了handle方法,而且self.request == conn msg = self.request.recv(1024).decode('utf-8') self.request.send('1'.encode('utf-8')) msg = self.request.recv(1024).decode('utf-8') self.request.send('2'.encode('utf-8')) msg = self.request.recv(1024).decode('utf-8') self.request.send('3'.encode('utf-8')) server = socketserver.ThreadingTCPServer(('127.0.0.1',9000),Myserver) server.serve_forever() # client.py import socket import time sk = socket.socket() sk.connect(('127.0.0.1',9000)) for i in range(3): sk.send(b'hello,yuan') msg = sk.recv(1024) print(msg) time.sleep(1) sk.close()
客户端是提供给 用户使用的 —— 登录验证
你的用户 就能看到你的client端源码了,用户就不须要本身写客户端了
客户端是提供给 机器使用的 —— 验证客户端的合法性
防止非法用户进入服务端窃取内部重要信息
# server.py import os import hashlib import socket def get_md5(secret_key,randseq): md5 = hashlib.md5(secret_key) md5.update(randseq) res = md5.hexdigest() return res def chat(conn): while True: msg = conn.recv(1024).decode('utf-8') print(msg) conn.send(msg.upper().encode('utf-8')) sk = socket.socket() sk.bind(('127.0.0.1',9000)) sk.listen() secret_key = b'names' while True: conn,addr = sk.accept() randseq = os.urandom(32) conn.send(randseq) md5code = get_md5(secret_key,randseq) ret = conn.recv(32).decode('utf-8') print(ret) if ret == md5code: print('是合法的客户端') chat(conn) else: print('不是合法的客户端') conn.close() sk.close() # client.py import hashlib import socket import time def get_md5(secret_key,randseq): md5 = hashlib.md5(secret_key) md5.update(randseq) res = md5.hexdigest() return res def chat(sk): while True: sk.send(b'hello') msg = sk.recv(1024).decode('utf-8') print(msg) time.sleep(0.5) sk = socket.socket() sk.connect(('127.0.0.1',9000)) secret_key = b'names' randseq = sk.recv(32) md5code = get_md5(secret_key,randseq) sk.send(md5code.encode('utf-8')) chat(sk) sk.close()