zoukankan      html  css  js  c++  java
  • 8.7网络编程(二)

    socket(套接字)

    1.服务端

    import socket
    
    server = socket.socket()  # 买手机 不传参数默认用的就是TCP协议
    server.bind(('127.0.0.1',8080))  # bind((host,port))  插电话卡  绑定ip和端口
    server.listen(5)  # 开机    半连接池
    conn, addr = server.accept()  # 接听电话  等着别人给你打电话     阻塞
    data = conn.recv(1024)  # 听别人说话 接收1024个字节数据          阻塞
    print(data)
    conn.send(b'hello baby~')  # 给别人回话
    conn.close()  # 挂电话
    server.close()  # 关机

    2.客户端

    import socket
    
    client = socket.socket()  # 拿电话
    client.connect(('127.0.0.1',8080))  # 拨号   写的是对方的ip和port
    client.send(b'hello world!')  # 对别人说话
    data = client.recv(1024)  # 听别人说话
    print(data)
    client.close()  # 挂电话

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

      send与recv对应,不要出现两边都是相同的情况

      recv是向内存要数据,至于数据的来源,你无需考虑

    连续循环和通信循环

    1.服务端

    import socket
    """
    服务端
        固定的ip和port
        24小时不间断提供服务
    """
    server = socket.socket()  # 生成一个对象
    server.bind(('127.0.0.1',8080))  # 绑定ip和port
    server.listen(5)  # 半连接池
    while True:
        conn, addr = server.accept()  # 等到别人来  conn就类似于是双向通道
        print(addr)  # ('127.0.0.1', 51323) 客户端的地址
        while True:
            try:
                data = conn.recv(1024)
                print(data)  # b''  针对mac与linux 客户端异常退出之后 服务端不会报错 只会一直接收b''
                if len(data) == 0:break
                conn.send(data.upper())
            except ConnectionResetError as e:
                print(e)
                break
        conn.close()

    2.客户端

    import socket
    
    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)
        data = client.recv(1024)
        print(data)

      半连接池:限制的是同一时刻的交互请求数

      有一个用户正在与服务器交互的话,其他用户无法交互,限制的是最大的等待数

    TCP粘包问题

    1.TCP特点,粘包问题:

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

    # 服务端
    import socket
    
    server = socket.socket()  # 买手机 不传参数默认用的就是TCP协议
    server.bind(('127.0.0.1',8080))  # bind((host,port))  插电话卡  绑定ip和端口
    server.listen(5)  # 开机    半连接池
    
    conn, addr = server.accept()  # 接听电话  等着别人给你打电话     阻塞
    data = conn.recv(1024)  # 听别人说话 接收1024个字节数据          阻塞
    print(data)
    data = conn.recv(1024)  # 听别人说话 接收1024个字节数据          阻塞
    print(data)
    data = conn.recv(1024)  # 听别人说话 接收1024个字节数据          阻塞
    print(data)
    # 客户端
    import socket
    
    client = socket.socket()  # 拿电话
    client.connect(('127.0.0.1',8080))  # 拨号   写的是对方的ip和port
    
    client.send(b'hello')
    client.send(b'world')
    client.send(b'baby')

    2.如何解决粘包问题

      struct模块

    struct模块

    1.服务端

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

      1.先制作一个发送给客户端的字典
      2.制作字典的报头
      3.发送字典的报头
      4.发送字典
      5.再发真实数据

    2.客户端

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

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

  • 相关阅读:
    sqlmap使用和X-Forwarded-For注入漏洞测试
    Spring 配置文件中将common.properties文件外置
    git rebase 和 reset的区别
    fatal: Not a valid object name: 'master'.
    Git error on commit after merge
    git 常用命令使用
    git常用命令学习
    关于idea 修改jsp文件后不能生效
    mysql 表被锁处理方案
    Redis 基本操作
  • 原文地址:https://www.cnblogs.com/francis1/p/11318307.html
Copyright © 2011-2022 走看看