• (网络编程)基于tcp(粘包问题) udp协议的套接字通信


    import   socket

    1.通信套接字(1人1句)服务端和1个客户端

    2.通信循环(1人多句)服务端和1个客户端

    3.通信循环(多人(串行)多句)多个客户端(服务端服务死:1个客户端--->下一个客户端...)

    基于上面的基础:实现远程执行命令

      发现问题:send(cmd)  

          recv() send(命令结果)

          recv(1024)命令结果没收完

       粘包问题: 主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。

    解决   自定义报头固定长度 import struct

      b=struct.pack('模式',数字)   #bytes  'i'->4,.....

      b1=srtuct.unpack('模式',b)  #元组

      len=b1[0]

      send(b) recv(4)

    from socket import *
    import struct
    import json

    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'))
    #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()

    from socket import *
    import subprocess
    import struct
    import json

    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:
    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()
    
    

    基于UDP协议通信的套接字

    TCP(流式协议):可靠性高。会因为网络原因丢包,但只有在一端收到另一端发来的ack确认信息才会将信息在内存中删除,如果发现丢包(一段时间内没有回复)会将信息再发一份。TCP会存在粘包问题,收与发可以不是对应的。必须先启动服务端,否则报错。

    UDP(数据包协议):可靠性低。信息一旦发出即在内存中删除,如果发生丢包,信息即丢失。UDP效率高速度快的主要原因,一是因为不建连接,二是因为接受后不会确认。 UDP没有粘包问题,收与发一一对应。 如果发hello,但收一个字符,在windows系统中会报错;在linunx系统中不报错,只接收h

    服务端

    import socket

    s=socket.socket(socket.AF_INET,spcket.SOCK.DGRAN)

    s.bind(('127.0.0.1',8080))

    msg,crrent_adress=s.recvfrom(1024)

    s.sendto(msg,crrent_adress)  

         

          

  • 相关阅读:
    HTTP报文
    Linux命令行下快捷键
    ruby离线安装整理
    Tomcat启动时卡在 INFO HostConfig.deployDirectory Deploy
    ruby在线安装整理
    python_控制台输出带颜色的文字方法
    http proxy模块参数
    upstream模块调度算法
    upstream模块介绍
    nginx的upstream目前支持5种方式的分配
  • 原文地址:https://www.cnblogs.com/3sss-ss-s/p/9579374.html
Copyright © 2020-2023  润新知