网络编程 之 套接字

  • 本地回环地址
    127.0.0.1 只能自己识别自己,其他人无法访问
  • TCP特点
    将数据量较小的并且时间间隔比较短的数据,一次性打包发给对方
  • 一个简单的CS架构
    # server端口
    import socket  # 导入socket模块
    server = socket.socket()  # 生成一个对象
    server.bind(('127.0.0.1', 8080))  # 把地址绑定到套接字​​​​
    conn, sddr = server.accept()  # 接收客户端链接
    ret = conn.recv(1024)  # 接收客户端信息
    print(ret)  # 打印客户端信息​​
    ​​conn.send(b'hi')  # 向客户端发送信息
    conn.close()  # 关闭客户端套接字
    server.close()  # 关闭服务器套接字(可选)​​
    # client端
    
    ​​​​import socket  # 导入socket模块
    client = socket.socket()  # 创建客户端套接字
    client.connect(('127.0.0.1', 8808))  # 连接服务器
    slient.send(b'hello!')​​​  # 向客户端发送信息
    ret = client.recv(1024)​  # 接口服务端信息
    prient(ret)  # 打印服务端发送来的信息
    client.close()​​  # 关闭客户端套接字
    View Code

      

  • 粘包问题
    • 什么是粘包问题
      对方发过来多个数据包,导致无法确认分割的大小
    • 解决粘包问题
      思路:用字典存储原数据报头的方式
    • 服务端:
      1.先制作一个发送给​​客户端的字典
      2.制作字典报头
      3.发送字典报头
      4.发送字典
      5.再发送真实数据
    • 客户端:
      1.先接收字典报头
      2.解析拿到的字典数据长度
      3.接收字典
      4.从字典中获取真实数据长度
      5.接收真实数据​​​​​​​​​​
    • 解决粘包代码
      import socket
      import subprocess
      import struct
      import json
      
      
      server = socket.socket()
      server.bind(('127.0.0.1',8080))
      server.listen(5)
      
      
      while True:
          conn, addr = server.accept()
          while True:
              try:
                  cmd = conn.recv(1024)
                  if len(cmd) == 0:break
                  cmd = cmd.decode('utf-8')
                  obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
                  res = obj.stdout.read() + obj.stderr.read()
                  d = {'name':'jason','file_size':len(res),'info':'asdhjkshasdad'}
                  json_d = json.dumps(d)
                  # 1.先制作一个字典的报头
                  header = struct.pack('i',len(json_d))
                  # 2.发送字典报头
                  conn.send(header)
                  # 3.发送字典
                  conn.send(json_d.encode('utf-8'))
                  # 4.再发真实数据
                  conn.send(res)
                  # conn.send(obj.stdout.read())
                  # conn.send(obj.stderr.read())
              except ConnectionResetError:
                  break
          conn.close()
      服务端
    • import socket
      import struct
      import json
      
      client = socket.socket()
      client.connect(('127.0.0.1',8080))
      
      while True:
          msg = input('>>>:').encode('utf-8')
          if len(msg) == 0:continue
          client.send(msg)
          # 1.先接受字典报头
          header_dict = client.recv(4)
          # 2.解析报头 获取字典的长度
          dict_size = struct.unpack('i',header_dict)[0]  # 解包的时候一定要加上索引0
          # 3.接收字典数据
          dict_bytes = client.recv(dict_size)
          dict_json = json.loads(dict_bytes.decode('utf-8'))
          # 4.从字典中获取信息
          print(dict_json)
          recv_size = 0
          real_data = b''
          while recv_size < dict_json.get('file_size'):  # real_size = 102400
              data = client.recv(1024)
              real_data += data
              recv_size += len(data)
          print(real_data.decode('gbk'))
      客户端

       


 

posted @ 2019-08-07 21:15  不在一城  阅读(124)  评论(0编辑  收藏  举报