TCP协议的粘包问题
文件发送自定义协议
TCP和UDP的特点
三次握手
accept 接受过程中等待客户端的连接
connect 客户端会发起一个syn连接请求
三次握手的过程在代码中是由accept和connet共同完成的,具体的细节在socket中没有体现出来。
四次挥手
# Server.py 阻塞IO模型
import socket
sk = socket.socket()
sk.bind((‘127.0.0.1‘, 9000))
sk.listen()
conn, addr = sk.accept() # 阻塞:数据不来一直等
print(conn)
# Server.py 非阻塞IO模型
import socket
sk = socket.socket()
sk.bind((‘127.0.0.1‘, 9000))
sk.setblocking(False) # 设置一个阻塞为非
sk.listen()
conn_lst = []
del_lst = []
while True:
    try:
        conn, addr = sk.accept() 
        print(conn)
        conn_lst.append(conn)
    except BlockingIOError:
        for c in conn_lst:
            try:
            	msg = c.recv(1024).decode(‘utf-8‘)
                if not msg:
                    del_lst.append(c)
                    continue
            	print(msg)
                c.send(msg.upper().encode(‘uft-8‘))
            except BlockingIOError:
                pass
        for c in del_lst:
            conn_lst.remove(c)
        del_lst.clear()
# Client.py
import time
import socket
sk = socket.socket()
sk.connect((‘127.0.0.1‘, 9000))
while True:
    sk.send(b‘alex‘)
    msg = sk.recv(1024)
    print(msg)
    time.sleep(0.2)
虽然非阻塞提高了CPU的利用率,但是耗费CPU做了很多无用功。
# Server.py
import os
import socket
import hashlib
def get_md5(secret_key, rad):
    md5 = hashlib.md5(secret_key)
    md5.update(rad)
    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‘alex‘
while True:
    conn, _ = sk.accept()
    rad = os.urandom(32)
    conn.send(rad)
    md5_code = get_md5(secret_key, rad)
    ret = conn.recv(1024).decode(‘utf-8‘)
    print(ret)
    if md5_code == ret:
        print(‘合法客户端‘)
        chat(conn)
    else:
        print(‘不合法客户端‘)
        conn.close()
sk.close()
# Client.py
import time
import socket
import hashlib
def get_md5(secret_key, rad):
    md5 = hashlib.md5(secret_key)
    md5.update(rad)
    res = md5.hexdigest()
    return res
def chat(sk):
    while True:
        sk.send(b‘hellow‘)
        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‘alex‘
rad = sk.recv(32)
md5_code = get_md5(secret_key, rad)
sk.send(md5_code.encode(‘utf-8‘))
chat(sk)
sk.close()
hmac模块
import os
import hmac
secret_key = b‘alex‘
random_seq = os.urandom(32)
hmac = hmac.new(secret_key, random_seq)
ret = hmac.digest() # 直接获得字节流对象
print(ret)
print(len(ret))
直接实现TCP协议可并发的Server端
# Server.py
import socketserver
class Myserver(socketserver.BaseRequestHandler):
    def handle(self): # 自动触发 handle 方法,并且self.request == conn
        print(self.request)
        while True:
            msg = self.request.recv(1024).decode(‘utf-8‘)
            print(msg)
            self.request.send(msg.upper().encode(‘utf-8‘))
server = socketserver.ThreadingTCPServer((‘127.0.0.1‘, 9000), Myserver)
server.serve_forever()
import re
from functools import reduce
def exp_format(exp):
    exp = exp.replace(‘--‘, ‘+‘)
    exp = exp.replace(‘+-‘, ‘-‘)
    exp = exp.replace(‘++‘, ‘+‘)
    exp = exp.replace(‘-+‘, ‘-‘)
    return exp
def mul_div(atom_exp):  # 最基础两个数的乘除法
    if ‘*‘ in atom_exp:
    	a, b = atom_exp.split(‘*‘)
        res = float(a) * float (b)
    else:
        a, b = atom_exp.split(‘/‘)
        res = float(a) / float(b)
    return res
def cal_muldiv(exp):
     com = re.compile(‘\d+(\.\d+)?[*/]-?\d+(\.\d+)?‘)  
     while True:
        obj = com.search(exp)  
        if obj:
             atom_exp = obj.group()
             res = mul_div(atom_exp)
             exp = exp.replace(atom_exp, str(res))
             exp = exp_format(exp)
         else:
             break
     return exp  # 只有加减法的表达式
def cal_addsub(exp): # 计算加减法
    ret = re.findall(‘[-+]?\d+(?:\.\d+)?‘, exp)
    count = reduce(lambda x,y:float(x)+float(y),ret)
    return count
def cal(no_bracket_exp):  # 完成最基本的加减乘除四则运算
    sub_exp = cal_muldiv(no_bracket_exp) # 做乘除法得到加减表达式
    sub_exp = exp_format(sub_exp) # 符号整理
    ret = cal_addsub(sub_exp) # 计算加减法
    return ret
    
def remove_backet(exp): # 去括号
    while True:
        ret = re.search(‘\([^()]+\)‘, exp)
        if ret:
            no_bracket_exp = ret.group()
            ret = cal(no_bracket_exp)
            exp = exp.replace(no_bracket_exp, str(ret))
        else:
            return exp
        
def main(exp):
    exp = exp.replace(‘ ‘, ‘‘)
    exp = exp_format(exp)
    exp = remove_backet(exp)
    return cal(exp)
原文:https://www.cnblogs.com/elliottwave/p/12639932.html