Python套接字,,一.基于tcp的套接


一.基于tcp的套接字

  tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端

  tcp服务端

from socket import *# 服务端必须满足至少三点:# 1.绑定一个固定的ip和port# 2.一直对外提供服务,稳定运行# 3.能够支持并发server = socket(AF_INET, SOCK_STREAM)server.bind((‘127.0.0.1‘, 9555))server.listen(5)client, addr = server.accept()data = client.recv(1024)print(data.decode(‘utf-8‘))client.send(data.upper())client.close()server.close()

  tcp客户端

from socket import *client = socket(AF_INET,SOCK_STREAM)client.connect((‘127.0.0.1‘,9555))msg = input(‘>>>:‘).strip()client.send(msg.encode(‘utf-8‘))data = client.recv(1024)print(data)client.close()

二.修改bug+通信循环+链接循环

  上述存在客户端退出时服务端即会崩溃的bug,而且无法实现用户的多次输入,以及服务端无法一直对外服务的问题,对此进行修改

  服务端

from socket import *server = socket(AF_INET, SOCK_STREAM)server.bind((‘127.0.0.1‘, 8081))server.listen(5)# 链接循环while True:    conn, client_addr = server.accept()    print(client_addr)    # 通信循环    while True:        try:            data = conn.recv(1024)            if len(data) == 0: break  # 针对linux系统            print(‘-->收到客户端的消息: ‘, data)            conn.send(data.upper())        except ConnectionResetError:            break    conn.close()server.close()

  客户端

from socket import *client = socket(AF_INET, SOCK_STREAM)client.connect((‘127.0.0.1‘, 8081))# 通信循环while True:    msg=input(‘>>: ‘).strip() #msg=‘‘    if len(msg) == 0:continue    client.send(msg.encode(‘utf-8‘)) #client.send(b‘‘)    # print(‘has send‘)    data=client.recv(1024)    # print(‘has recv‘)    print(data)client.close()

三.模拟ssh实现远程执行命令

技术分享图片
from socket import *import subprocessserver = socket(AF_INET, SOCK_STREAM)server.bind((‘127.0.0.1‘, 8081))server.listen(5)# 链接循环while True:    conn, client_addr = server.accept()    print(client_addr)    # 通信循环    while True:        try:            cmd = conn.recv(1024) #cmd=b‘dir‘            if len(cmd) == 0: break  # 针对linux系统            obj=subprocess.Popen(cmd.decode(‘utf-8‘),                             shell=True,                             stdout=subprocess.PIPE,                             stderr=subprocess.PIPE                             )            stdout=obj.stdout.read()            stderr=obj.stderr.read()            print(len(stdout) + len(stderr))            conn.send(stdout+stderr)        except ConnectionResetError:            break    conn.close()server.close()
服务端技术分享图片
from socket import *client = socket(AF_INET, SOCK_STREAM)client.connect((‘127.0.0.1‘, 8081))# 通信循环while True:    cmd=input(‘>>: ‘).strip()    if len(cmd) == 0:continue    client.send(cmd.encode(‘utf-8‘))    cmd_res=client.recv(1024000)    print(cmd_res.decode(‘gbk‘))client.close()
客户端

四.粘包问题以及解决方法

  粘包问题:

    只有TCP有粘包现象,UDP不存在粘包,粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的.

  简单粘包问题案例

技术分享图片
from socket import *import subprocessserver = socket(AF_INET, SOCK_STREAM)server.bind((‘127.0.0.1‘, 8081))server.listen(5)conn,_=server.accept()data1=conn.recv(5)print(‘第一次收: ‘,data1)data2=conn.recv(5)print(‘第二次收: ‘,data2)data3=conn.recv(4)print(‘第三次收: ‘,data3)# 粘包问题是tcp协议流式传输数据的方式导致的# 如何解决粘包问题:接收端能够精确地收干净每个数据包没有任何残留
服务端技术分享图片
from socket import *client = socket(AF_INET, SOCK_STREAM)client.connect((‘127.0.0.1‘, 8081))# tcp协议会将数据量较小且发送时间间隔较短的数据合并成一个数据报发送client.send(b‘hello‘)client.send(b‘world‘)client.send(b‘egon‘)
客户端

五.解决粘包问题

技术分享图片
from socket import *import subprocessimport structimport jsonserver = socket(AF_INET, SOCK_STREAM)server.bind((‘127.0.0.1‘, 8081))server.listen(5)# 链接循环while True:    conn, client_addr = server.accept()    print(client_addr)    # 通信循环    while True:        try:            cmd = conn.recv(1024)  # cmd=b‘dir‘            if len(cmd) == 0: break  # 针对linux系统            obj = subprocess.Popen(cmd.decode(‘utf-8‘),                                   shell=True,                                   stdout=subprocess.PIPE,                                   stderr=subprocess.PIPE                                   )            stdout = obj.stdout.read()            stderr = obj.stderr.read()            # 1. 先制作报头            header_dic = {                ‘filename‘: ‘a.txt‘,                ‘md5‘: ‘asdfasdf123123x1‘,                ‘total_size‘: len(stdout) + len(stderr)            }            header_json = json.dumps(header_dic)            header_bytes = header_json.encode(‘utf-8‘)            # 2. 先发送4个bytes(包含报头的长度)            conn.send(struct.pack(‘i‘, len(header_bytes)))            # 3  再发送报头            conn.send(header_bytes)            # 4. 最后发送真实的数据            conn.send(stdout)            conn.send(stderr)        except ConnectionResetError:            break    conn.close()server.close()
服务端技术分享图片
from socket import *import structimport jsonclient = socket(AF_INET, SOCK_STREAM)client.connect((‘127.0.0.1‘, 8081))# 通信循环while True:    cmd = input(‘>>: ‘).strip()    if len(cmd) == 0: continue    client.send(cmd.encode(‘utf-8‘))    # 1. 先收4bytes,解出报头的长度    header_size = struct.unpack(‘i‘, client.recv(4))[0]    # 2. 再接收报头,拿到header_dic    header_bytes = client.recv(header_size)    header_json = header_bytes.decode(‘utf-8‘)    header_dic = json.loads(header_json)    print(header_dic)    total_size = header_dic[‘total_size‘]    # 3. 接收真正的数据    cmd_res = b‘‘    recv_size = 0    while recv_size < total_size:        data = client.recv(1024)        recv_size += len(data)        cmd_res += data    print(cmd_res.decode(‘gbk‘))client.close()
客户端

    

Python套接字

评论关闭