• TCP通信: scoket模块 黏包问题 连接循环 通信循环


    scoket模块

    简单版本原理解析:

    服务端的设置:

    客户端的设置:

    注意:

      127.0.0.1为本机回还地址(只能自己识别自己,其他人无法访问!)

      send 和 recv要相对应,不能出现两边同时接收或发送的情况!

      recv 接收的数据是来自内存的,至于是谁发送到内存的无需考虑。

    TCP特点:

        会将数据量小的并且时间间隔短的数据一次性打包发送给对方。

    解决黏包问题:

    服务端:

      1.先制作一个发送给客户端的字典

      2.制作字典的报头

      3.发送字典的报头

      4.发送字典

      5.再发真实数据

    客户端:

      1.先接受字典的报头
      2.解析拿到字典的数据长度
      3.接受字典
      4.从字典中获取真实数据的长度
      5.接受真实数据

    struct 模块:

      用于固定发送数据的长度。

      res = struct.pack('i',len(一个值))

      stuct.unpack('i',res)[0]

     1 客户端设置:
     2 import socket
     3 import struct
     4 import json
     5 client = socket.socket()
     6 client.connect(('127.0.0.1',8080))
     7 while True:
     8     msg = input('请输入指令:').encode('utf-8')
     9     client.send(msg)
    10     if len(msg) == 0:continue
    11     header = client.recv(4)
    12     dict_size = struct.unpack('i',header)[0]
    13     dict = client.recv(dict_size)
    14     dict_json = json.loads(dict.decode('utf-8'))
    15     print(dict_json)
    16     recv_size = 0
    17     real_data = b''
    18     while recv_size < dict_json.get('file_size'):
    19         data = client.recv(1024)
    20         real_data += data
    21         recv_size += len(data)
    22     print(real_data.decode('gbk'))
    23 服务端设置:
    24 import socket
    25 import subprocess
    26 import json
    27 import struct
    28 server = socket.socket()
    29 server.bind(('127.0.0.1',8080))
    30 server.listen(5)
    31 
    32 while True:
    33     conn, addr = server.accept()
    34     while True:
    35         try:
    36             cmd = conn.recv(1024)
    37             if len(cmd) == 0:break
    38             cmd = cmd.decode('utf-8')
    39             obj = subprocess.Popen(
    40                 cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    41             res = obj.stdout.read()+obj.stderr.read()
    42             d = {'name':'yyj', 'file_size':len(res)}
    43             json_d = json.dumps(d)
    44             header = struct.pack('i',len(json_d))
    45             conn.send(header)
    46             conn.send(json_d.encode('utf-8'))
    47             conn.send(res)
    48         except ConnectionResetError as e:
    49             print(e)
    50             break
    51     conn.close()
    View Code

    连接循环和通信循环的设计:

     1 #服务端:
     2 import socket
     3 
     4 """
     5 服务端
     6     固定的ip和port
     7     24小时不间断提供服务
     8 """
     9 server = socket.socket()  # 生成一个对象
    10 server.bind(('127.0.0.1',8080))  # 绑定ip和port
    11 server.listen(5)  # 半连接池
    12 
    13 while True:
    14     conn, addr = server.accept()  # 等到别人来  conn就类似于是双向通道
    15     print(addr)  # ('127.0.0.1', 51323) 客户端的地址
    16     while True:
    17         try:
    18             data = conn.recv(1024)
    19             print(data)  # b''  针对mac与linux 客户端异常退出之后 服务端不会报错 只会一直收b''
    20             if len(data) == 0:break
    21             conn.send(data.upper())
    22         except ConnectionResetError as e:
    23             print(e)
    24             break
    25     conn.close()
    26 
    27 客户端:
    28 import socket
    29 
    30 
    31 client = socket.socket()
    32 client.connect(('127.0.0.1',8080))
    33 
    34 while True:
    35     msg = input('>>>:').encode('utf-8')
    36     if len(msg) == 0:continue
    37     client.send(msg)
    38     data = client.recv(1024)
    39     print(data)
    View Code

    用于处理服务端重新启动时端口没有及时释放问题:

      from socket import SOL_SOCKET,SO_REUSEADDR

      sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加

  • 相关阅读:
    获取其他进程中StatusBar的文本
    TStringGrid多选的复制与拷贝
    常用数据结构
    数据结构及算法
    时间复杂度和空间复杂度详解
    算法的时间复杂度和空间复杂度
    新增并管理媒体资源
    Node.js与MongoDB的基本连接示例
    Web API 2:Action的返回类型
    快递查询组件
  • 原文地址:https://www.cnblogs.com/yangjiaoshou/p/11317774.html
Copyright © 2020-2023  润新知