首页 > 其他分享 >(4)socket套接字使用模版

(4)socket套接字使用模版

时间:2023-06-23 17:33:51浏览次数:48  
标签:socket 模版 server --- json msg 接字 size 字节

socket套接字使用模版

【一】客户端

# -*-coding: Utf-8 -*-
# @File : 客户端 .py
# author: Chimengmeng
# blog_url : https://www.cnblogs.com/dream-ze/
# Time:2023/6/22
import json
from socket import *

# 解指定数据长度
import struct

# 创建  socket 对象
client = socket(AF_INET, SOCK_STREAM)

# 创建链接 IP 和 端口
client.connect(('127.0.0.1', 8085))

while True:
    msg = input('enter msg :>>>').strip()

    # 输入的内容不能为空
    if len(msg) == 0:
        continue

    # 传输过程中的数据为二进制数据。对文本数据进行转码
    msg = msg.encode('utf-8')
    client.send(msg)

    # 接收来自服务端返回的结果

    # (1.1) 先收四个字节的数据,从接收到的数据中解析出json格式的二进制数据的长度
    json_data_size_unpack = client.recv(4)

    # 解包返回的是元祖。元祖第一个参数就是打包的数字
    json_data_size = struct.unpack('i', json_data_size_unpack)[0]

    # (1.2) 对 服务端 返回的数据中指定长度进行截取 拿到 json 格式的二进制数据
    json_data_bytes = client.recv(json_data_size)

    # (1.3) 对指定数据进行json格式的解码并取出需要的信息
    header_dict_str = json_data_bytes.decode('utf-8')
    header_dict = json.loads(header_dict_str)

    # (1.4) 取出字典中的信息总长度
    recv_total_size = header_dict['total_size']

    # (2) 接收真实的数据
    # recv_size = 0 ,循环接收,每接收一次,recv_size += 接收的长度
    # (3) 直到 recv_size = recv_total_size 表示接受信息完毕,结束循环
    # 初始化数据长度
    recv_size = 0
    while recv_size < recv_total_size:
        # 本次接收 最多能接收 1024 字节的数据
        msg_from_server = client.recv(1024)
        # 本次接收到的打印的数据长度
        recv_size += len(msg_from_server)

        # 对服务端返回的信息进行解码(Mac/Linux解码用utf-8,Windows用GBK)
        msg_from_server = msg_from_server.decode('gbk')
        print(msg_from_server, end='')

    else:
        print('命令结束')

    client.close()

【二】服务端

# -*-coding: Utf-8 -*-
# @File : 服务端 .py
# author: Chimengmeng
# blog_url : https://www.cnblogs.com/dream-ze/
# Time:2023/6/22

# client.connect(('127.0.0.1', 8880))
# 客户端设置的 ip 和 port
from socket import *

# 执行命令模块
import subprocess
# 将数据打包成指定4个长度的数据
import struct
# 将头部信息转成json格式(通用信息格式)
import json

# (1)创建服务对象
# 参数 : AF_INET(默认,初始化操作)
# 参数 : SOCK_STREAM(流式传输协议)
server = socket(AF_INET, SOCK_STREAM)

# (2)建立链接桥梁 --(呼应客户端的 ip 和 port)
IP = '127.0.0.1'
PORT = 8080
server.bind((IP, PORT))

# (3)指定半连接池大小
server.listen(5)

# (4)接收数据和发送数据
while True:
    # (4.1)从半连接池里面取出链接请求,建立双向链接,拿到连接对象
    # (4.2)返回参数解压赋值 : (建成的链接对象,客户端的 ip port)
    conn, client_addr = server.accept()

    while True:
        # (5)检测可能会抛出的异常 并 对异常做处理
        try:
            # (5.1)基于 取出的链接对象 进行通信
            # (5.2)接受客户端传入的指定信息
            cmd_from_client = conn.recv(1024)

            # 不允许传过来的信息为空
            if len(cmd_from_client) == 0:
                break

            # (5.3)通过subprocess模块,执行客户端传过来的命令
            # (5.3.1)接收执行命令的结果
            msg_server = subprocess.Popen(cmd_from_client.decode('utf-8'),  # 对命令进行解码
                                          shell=True,  # 执行shell命令
                                          stdout=subprocess.PIPE,  # 管道一
                                          stderr=subprocess.PIPE,  # 管道二
                                          )

            # (5.3.2)返回命令的结果  ---- 成功或失败
            # ****** 对于返回给客户端的数据,客户端 Linux系统可以用utf-8解码,Windows系统需要用gbk解码 ******
            true_msg = msg_server.stdout.read()  # 读取到执行成功的结果 ---- 二进制数据类型
            false_msg = msg_server.stderr.read()  # 读取到执行失败的结果 ---- 二进制数据类型

            # (5.4):头部信息(程序执行的结果,成功信息长度 + 失败信息长度)
            total_size_from_server = len(true_msg) + len(false_msg)

            # (5.5)自定义头部信息(存储任意数据拼接数据)
            headers_dict = {
                'file_name': 'a.txt',
                'total_size': total_size_from_server,
                'md5': 'md5'
            }

            # (5.6)打包头部信息 - 将字典转成 json 格式数据类型
            json_data_str = json.dumps(headers_dict)
            # (5.7)将 json 格式数据转成二进制数据传输
            json_data_bytes = json_data_str.encode('utf-8')

            # (5.8)int类型  -----> 将json格式的二进制数据打成固定长度的 bytes
            # 参数 i 表示是整型,具体解释参考文档
            json_data_size_pack = struct.pack('i', len(json_data_bytes))
            conn.send(json_data_size_pack)

            # (5.9)发送打包好的头信息
            conn.send(json_data_bytes)

            # (5.10)反馈信息(成功信息 + 失败信息)给 发送信息的客户端
            conn.send(true_msg)
            conn.send(false_msg)

        except Exception as e:
            
            break
    # 关闭服务端
    conn.close()

【三】struct模块参数详解

struct.pack()是Python内置模块struct中的一个函数,它的作用是将指定的数据按照指定的格式进行打包,并将打包后的结果转换成一个字节序列(byte string),可以用于在网络上传输或者储存于文件中。

struct.pack(fmt, v1, v2, ...)

其中,fmt为格式字符串,指定了需要打包的数据的格式,后面的v1,v2,...则是需要打包的数据。这些数据会按照fmt的格式被编码成二进制的字节串,并返回这个字节串。

fmt的常用格式符如下:

  • x --- 填充字节
  • c --- char类型,占1字节
  • b --- signed char类型,占1字节
  • B --- unsigned char类型,占1字节
  • h --- short类型,占2字节
  • H --- unsigned short类型,占2字节
  • i --- int类型,占4字节
  • I --- unsigned int类型,占4字节
  • l --- long类型,占4字节(32位机器上)或者8字节(64位机器上)
  • L --- unsigned long类型,占4字节(32位机器上)或者8字节(64位机器上)
  • q --- long long类型,占8字节
  • Q --- unsigned long long类型,占8字节
  • f --- float类型,占4字节
  • d --- double类型,占8字节
  • s --- char[]类型,占指定字节个数,需要用数字指定长度
  • p --- char[]类型,跟s一样,但通常用来表示字符串
  • ? --- bool类型,占1字节

具体的格式化规则可以在Python文档中查看(链接)。

标签:socket,模版,server,---,json,msg,接字,size,字节
From: https://www.cnblogs.com/dream-ze/p/17499411.html

相关文章

  • 【六】socket层
    【六】socket层Socket它到底在哪里呢?还是用图来说话,一目了然。【1】socket是什么Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面对用户来说,一组简单的接口就是全部......
  • Python基于Socket编写TcpServer通信基本框架
    如下主要是实现单客户端连接通信,如下为Socket模块的常用属性和方法介绍。如要实现多客户端连接,请使用threading模块的多线程技术实现。属性:•socket.AF_INET:IPv4地址族。•socket.AF_INET6:IPv6地址族。•socket.SOCK_STREAM:TCP协议类型。•socket.SOCK_DGRAM:UDP协议类......
  • Uniapp仿ChatGPT Stream流式输出(非Websocket)
    前言最近写一个chagpt小程序,流式输出可以使用websocket也可以使用stream来实现,这里就不折腾websocket的了,我发现uniapp实现流式输出的方式挺多的,主要是有些小程序还不兼容,花了点时间研究了一下。EventSourceEventSource也称为SSE(Server-SentEvents),是服务器推送的一个网络事件......
  • permission denied while trying to connect to the Docker daemon socket at unix://
     001、问题[liujiaxin01@PC1~]$dockersearchomicsclasspermissiondeniedwhiletryingtoconnecttotheDockerdaemonsocketatunix:///var/run/docker.sock:Get"http://%2Fvar%2Frun%2Fdocker.sock/v1.24/images/search?term=omicsclass":dialunix......
  • fpga 以太网w5500 SPI传输80MHz,Alter FPGA verilog udp驱动源码,8个SOCKET都可用,SPI频
    fpga以太网w5500SPI传输80MHz,AlterFPGAverilogudp驱动源码,8个SOCKET都可用,SPI频率支持80MHZ,硬件验证以通过。w5500ip核w5500软核实测网络传输速度8.5M/s,学习必用之良品ID:1399607465825157......
  • fpga 以太网w5500 SPI传输80MHz FPGA verilog TCP客户端驱动源码,8个SOCKET都可用,SPI
    fpga以太网w5500SPI传输80MHzFPGAverilogTCP客户端驱动源码,8个SOCKET都可用,SPI频率80MHZ,硬件验证以通过。w5500ip核w5500软核,还有TCP服务端和UDP模式,联系联系我要那个,默认发TCP客户端。这个代码是用fpga驱动和使用w5500模块,做过优化,可能以达到w5500最高传输速度,学习必......
  • webView链接字串以及多点触摸问题
    packagefirsrdroid.tutorial.mywebview;importandroid.app.Activity;importandroid.os.Bundle;importandroid.webkit.WebView;importandroid.webkit.WebViewClient;publicclassUsingMyWebviewextendsActivity{WebViewmWebView;/**Calledwhentheact......
  • fpga 以太网w5500,SPI传输80MHz, Alte A收发verilog软核 ip核源码,W5500以太网模块, 1个
    fpga以太网w5500,SPI传输80MHz,AlteA收发verilog软核ip核源码,W5500以太网模块,1个SOCKET,需要多个SOCKET的可以做为参照进行修改,从而实现多个SOCKET的使用,学习必用之良品,还有51stm32驱动源码需要的可联系?这个代码只为描述w5500工作流程,有时序问题ID:1399606728731264......
  • Springboot实现WebSocket
    一、什么是webSocketWebSocket是HTML5下一种新的协议(Websocket协议本质上是一个基于tcp的协议),它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的,WebSocket是一个持久化的协议。二、修改配置文件在application.properties,修改内容为:server.port=......
  • springboot+websocket简单使用
    一、引入依赖<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.o......