zoukankan      html  css  js  c++  java
  • 初识socket之TCP协议

    TCP服务端、客户端(基础版本)

    # 这是服务端
    import socket

    server = socket.socket()  # 买手机
    server.bind(('127.0.0.1', 8080))  # 插手机卡   bind((IP,PORT))
    server.listen(5)  # 开机   半连接池


    conn, addr = server.accept()  # 待机等待接电话


    data = conn.recv(1024)  # 接听别人说话 只接收1024个字节 bytes
    print(data)
    conn.send(b'hello big baby!')  # 跟别人说话

    conn.close()  # 关闭通信连接,如果不关闭的话就跟文件open操作一样,没有close时还会存在于内存中,造成空间的浪费
    server.close()  # 关闭服务端
    # 这是客户端
    import socket  


    client = socket.socket()
    client.connect(('127.0.0.1',8080))  # 找服务器

    client.send(b'hello how much?')
    data = client.recv(1024)
    print(data)

    client.close()

     

    TCP内部传输优化(如果发送的数据较短且时间间隔很短,就好将它们打包成一个发过去,这也是粘包的一种。但是通常我们说的粘包指的是接收方不清楚发送方发送的数据大小,导致一次接收不完,下一次接收数据时里面会掺杂上一次未接收完的数据。)

    # 用以验证的服务端,该优化产生的粘包现象仅存在于客户端向服务端发送消息
    import socket

    server = socket.socket()
    server.bind(('127.0.0.1',8088))
    server.listen(5)  # 半连接池


    conn,addr = server.accept()
    data = conn.recv(4)
    print(data)
    data = conn.recv(5)
    print(data)
    data = conn.recv(5)
    print(data)
    # 用以验证的客户端
    import socket

    client = socket.socket()
    client.connect(('127.0.0.1',8088))


    client.send(b'hello')
    client.send(b'hello')
    client.send(b'hello')

     

    struct模块(用于处理粘包问题的模块之一)

     

    # struct模块的pack可以将无论多长的数据(其实能压缩的数据是有上限的)都打包成固定四个字节长度的数据,模式及详情见上图
    import struct


    data = 'dfsafsagdsfgfsdgsdfgfdsgsdfggsdgfdssfsdfsafsfdgsdfgsfdgsfdgsfdgsfdgsdfgdsfgsdfgsdgsdgjgjhghjghjgfjfghjfghjfgjdafsafdsafdsdafsdafsdafaf'
    # 服务端
    res = struct.pack('i',len(data))
    print(len(res))

    # print(res)
    # 客户端
    ret = struct.unpack('i',res)[0] # unpack返回的是一个元组,第一个(索引为0)才是我们自己的数据(这里是len(data))
    print(ret)

     

    TCP服务端、客户端(用发送报头的方式处理粘包问题)

    # 这是服务端server
    import socket
    import subprocess
    import struct
    import json
    """
    服务端:
    要有固定的ip和port
    24小时不间断提供服务
    """
    server = socket.socket()
    server.bind(('127.0.0.1',8081))
    server.listen(5)  # 半连接池

    while True: # 该whlie True里是链接循环accept负责链接客户端
       conn,addr = server.accept()  # 阻塞
       while True: #该while True里是通信循环
           try: # 这里用try异常捕获,因为客户端在非正常退出时服务端会报错,如果不捕获异常的话服务端程序就无法正常运行,它会崩
               data = conn.recv(1024).decode('utf-8')  # 阻塞
               if len(data) == 0:break  # 针对linux和mac系统 客户端异常断开反复收空的情况
               obj = subprocess.Popen(data,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) # subprocess模块是让电脑执行脚本命令的(如cmd命令)
               stdout = obj.stdout.read()
               stderr = obj.stderr.read()
               print(len(stdout+stderr))

               header_dic = {
                   'filename':'cls.av',
                   'len':len(stdout+stderr)
              }

               header_bytes = json.dumps(header_dic).encode('utf-8')
               # 制作报头
               header = struct.pack('i', len(header_bytes))  # 将需要发送给客户端的数据打包成固定4个字节
               conn.send(header) #发送报头,客户端recv(4)接收

               conn.send(header_bytes) #发送报头的字节格式

               conn.send(stdout+stderr)#发送真实数据

           except ConnectionResetError:
               break
       conn.close()

    server.close() # 该语句可以不要,因为服务端是要24小时提供服务的
    # 这是客户端client
    import socket
    import struct
    import json


    client = socket.socket()
    client.connect(('127.0.0.1',8081))


    while True:
       msg = input('>>>:').encode('utf-8')
       if len(msg) == 0:continue
       client.send(msg)
       header = client.recv(4) #接收报头

       # 对这个头进行解包,获取真实数据的长度
       head_len = struct.unpack('i',header)[0]
       head_dic = json.loads(client.recv(head_len).decode('utf-8'))
       print(head_dic)

       # 对需要接受的数据 进行循环接收
       total_size = head_dic['len']
       recv_size = 0
       res = b''
       while recv_size < total_size:
           data = client.recv(1024)
           res += data
           recv_size += len(data)
       print(res.decode('gbk')) # subprocess拿回的数据是系统执行脚本后的,windows系统默认编码是gbk,如果用utf8等非gbk编码会乱码

    #关于TCP三次挥手四次握手:https://www.cnblogs.com/huangxuanya/p/10796784.html

     

  • 相关阅读:
    推荐vue脚手架工具 vue-cli
    React仿大众点评外卖app
    推荐一个react脚手架工具
    eclipse 中配置php的 XDebug调试
    再谈extjs4.1中gridpanel动态表头动态列
    控制extsj4.1 gridpanel表格行或者单元格的编辑
    windows8.1 app所有默认样式
    windows8.1 app样式定义使用
    windows8.1 app入门开发学习
    Silverlight Tools 语言不匹配问题
  • 原文地址:https://www.cnblogs.com/maoruqiang/p/10885005.html
Copyright © 2011-2022 走看看