CSIC_716_20191205【TCP-解决粘包问题、UDP模板】

 

 

 

 

 

 

------------------------------------------------------------------------------------------------------------------------------------

 

 

 

 

 

 

 客户端代码模板:(以ssh为例)

# _*_ coding: gbk _*_
# @Author: Wonder

import socket
import json
import struct

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('172.16.10.19', 9527))

while True:
    try:
        cmd = input('>>>请输入指令').strip()
        if not cmd:
            continue
        if cmd == 'q':
            break
        cmd = cmd.encode('utf-8')
        dict_context = {
            'data_size': len(cmd)  # 二进制的长度
        }
        client_bytes = json.dumps(dict_context).encode('utf-8')  # dict----->json------->binary 报头
        head = struct.pack('i', len(client_bytes))  # struct 将报头长度巧妙的转为4 bit

        # 以下为一波socket三连发送操作。
        client.send(head)  # 发报头长度,

        client.send(client_bytes)  # 发报头,里面有实际数据的长度

        client.send(cmd)  # 传数据

        bin_head = client.recv(4)  # 接收来自server的报头信息
        json_head_len = struct.unpack('i', bin_head)[0]  # unpack  获取报文头长度
        head_json = client.recv(json_head_len).decode()  # 解码 获得 json格式的 报头字典
        dic_head = json.loads(head_json)  # 反序列化,得到 data的长度所在的字典
        size = dic_head.get('data_size')  # 取到data的真实长度值
        length = 0
        bin_toatal = b''

        while length < size:
            bin_content = client.recv(500)
            bin_toatal += bin_content
            length += len(bin_content)      # 此处要累加bin_content的长度
            print('当前下载进度',size , length , length / size)
        print('当前下载进度---------------->', length / size)

        print(bin_toatal.decode('gbk'))
except Exception as e: print(e) break client.close()

  

 

 服务端模板:

 

# _*_ coding: gbk _*_
# @Author: Wonder
import socket
import subprocess
import json
import struct

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('172.16.10.180', 9527))
server.listen(3)
while True:
    conn, addr = server.accept()
    while True:
        try:

            bin_head = conn.recv(4)  # 获取4位长度的报文头
            json_head = struct.unpack('i', bin_head)[0]  # 获得报头长度--->int

            bin_head = conn.recv(json_head).decode('utf-8')  # 获取报头信息 ------>binary----->JSON
            dic_head = json.loads(bin_head)  # 反序列化得到字典
            size = dic_head.get('data_size')  # 字典取值得到数据长度

            length = 0
            bin_toatal = b''
            while length < size:  # if 循环接收,直到长度和报头中的长度一致
                bin_content = conn.recv(50)
                bin_toatal += bin_content
                length += len(bin_toatal)

            cmd = bin_toatal.decode('utf-8')

            subprocess_obj = subprocess.Popen(cmd, shell=True,
                                              stdout=subprocess.PIPE,
                                              stderr=subprocess.PIPE)
            stdout = subprocess_obj.stdout.read()  # binary
            stderr = subprocess_obj.stderr.read()

            back_data_len = len(stderr) + len(stdout)
            print(back_data_len)

            server_dict = {
                'data_size': back_data_len  # 务必代表二进制的长度
            }
            back_json = json.dumps(server_dict).encode('utf-8')  # 序列化成  json字典  ------->json----->binary
            server_head = struct.pack('i', len(back_json))  # 转成4位长度的二进制, 表示报头长度
            conn.send(server_head)  # 发报头长度
            conn.send(back_json)  # 发报头
            conn.send(stdout)  # 发数据
            conn.send(stderr)

        except Exception as e:
            print(e)
            break
    conn.close()
server.close()

 

 

 

 

 

 UDP的初级使用

UDP服务端(即时通讯,你一句我一句)

# _*_ coding: gbk _*_
# @Author: Wonder
import socket

# 指定是 数据报,type= 一定要写,不然报错
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(
    ('127.0.0.1', 9527)
)

while True:
    data, addr = sk.recvfrom(1024)
    print(data.decode('utf-8'))
    sk.sendto('永不在线'.encode('UTF-8'), addr)

客户端要绑定, 接收是recvfrom ,接收的是data和addr ,发送是sendto,发送的是data和目标addr

 

UDP客户端

# _*_ coding: gbk _*_
# @Author: Wonder
import socket

sk = socket.socket(type=socket.SOCK_DGRAM)
addr = ('127.0.0.1', 9527)
while True:
    msg = input('>>>输入内容')
    if msg == 'q':
        break
    sk.sendto(msg.encode('utf-8'), addr)
    data, back = sk.recvfrom(1024)
    print(data.decode('utf-8'))

  

 

posted @ 2019-12-05 19:49  HEU葉孤城  阅读(171)  评论(0编辑  收藏  举报