14.7 Socket 循环结构体传输

news2024/11/28 4:53:29

在上述内容中笔者通过一个简单的案例给大家介绍了在套接字编程中如何传递结构体数据,本章将继续延申结构体传输,在某些时候例如我们需要传输一些当前系统的进程列表信息,或者是当前主机中的目录文件,此时就需要使用循环结构体传输功能,循环传输结构体的关键点在于,客户端发送结构体数据之前需要通过一次通信来告诉服务端需要接收的次数,当服务端接收到次数时则可利用接收计数器依次循环接收数据直到客户端完整所有数据包的发送。

14.7.1 服务端实现

多条结构体的传输方式与单条从原理上一致,只是多条结构体在传输时需要提前告知服务端我需要分几次将结构体传输给对方,因为数据包最大单次可发送8192字节,所以如果结构过多则需要分批次进行传输,如下是服务端实现代码片段,在代码中首先我们接收客户端发来的循环次数,该次数是一个字符串类型的,为了能用于循环体内,需要通过atoi(count)将其转换为一个整数,接着就是在循环体内不断地调用recv函数接收数据包,直到循环结束为止。

#include <iostream>
#include <winsock2.h>

#pragma comment(lib,"ws2_32.lib")

typedef struct
{
  char HostName[32];
  char Buffer[32];
}message;

int main(int argc, char* argv[])
{
  WSADATA WSAData;
  SOCKET sock;

  WSAStartup(MAKEWORD(2, 0), &WSAData);
  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock == INVALID_SOCKET)
  {
    std::cout << "创建套接字失败" << std::endl;
  }

  struct sockaddr_in ServerAddr;
  ServerAddr.sin_family = AF_INET;
  ServerAddr.sin_port = htons(9999);
  ServerAddr.sin_addr.s_addr = INADDR_ANY;

  auto res = bind(sock, (LPSOCKADDR)&ServerAddr, sizeof(ServerAddr));
  if (res == SOCKET_ERROR)
  {
    std::cout << "绑定失败" << std::endl;
  }

  res = listen(sock, 10);
  if (res == SOCKET_ERROR)
  {
    std::cout << "侦听失败" << std::endl;
  }

  SOCKET msgsock;

  msgsock = accept(sock, (LPSOCKADDR)0, (int*)0);
  if (msgsock != INVALID_SOCKET)
  {
    // 接收循环次数
    char count[32] = { 0 };
    int recv_count_flag = recv(msgsock, count, sizeof(count), 0);
    if (recv_count_flag != 0)
    {
      // 得到需要循环接收的次数
      int index = atoi(count);
      std::cout << "总共循环接收: " << count << " 次" << std::endl;
      
      for (int x = 0; x < index; x++)
      {
        char recv_buf[4096] = { 0 };

        // 循环输出接收结果
        int recv_flag = recv(msgsock, recv_buf, sizeof(recv_buf), 0);
        if (recv_flag != 0)
        {
          // 接收到结构,强制类型转换
          message* msg = (message*)recv_buf;

          std::cout << "用户名: " << msg->HostName << "数据: " << msg->Buffer << std::endl;

          // 发送成功标志
          send(msgsock, "success", 7, 0);
        }
      }
    }
  }

  closesocket(sock);
  WSACleanup();
  return 0;
}

14.7.2 客户端实现

相对于服务端而言,客户端首先需要准备好一个待发送结构体链表,此处通过使用vector<message>的方式接收结构体链表,并通过sprintf()函数将循环次数由整数格式化为字符串,并将次数发送给服务端,当服务端接收到发送次数后会等待客户端向其发送对应数量的结构体,此时客户端只需要send循环发送即可。

#include <iostream>
#include <vector>
#include <winsock2.h>

#pragma comment(lib,"ws2_32.lib")

using namespace std;

typedef struct
{
  char HostName[32];
  char Buffer[32];
}message;

message msg;

int main(int argc, char* argv[])
{
  WSADATA WSAData;
  SOCKET sock;

  WSAStartup(MAKEWORD(2, 0), &WSAData);
  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock == INVALID_SOCKET)
  {
    std::cout << "创建套接字失败" << std::endl;
  }

  struct sockaddr_in ClientAddr;
  ClientAddr.sin_family = AF_INET;
  ClientAddr.sin_port = htons(9999);
  ClientAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

  auto res = connect(sock, (LPSOCKADDR)&ClientAddr, sizeof(ClientAddr));

  if (res == SOCKET_ERROR)
  {
    std::cout << "链接失败." << std::endl;
  }

  // 模拟元素填充
  std::vector<message> vect;

  for (int x = 0; x < 10; x++)
  {
    message ptr;
    // 填充参数
    sprintf(ptr.HostName, "lyshark %d", x);
    sprintf(ptr.Buffer, "hello lyshark %d", x);
    vect.push_back(ptr);
  }

  // 发送循环次数
  char count[32] = { 0 };

  // 整数转为字符串
  sprintf(count, "%d", vect.size());

  int send_count_flag = send(sock, count, sizeof(count), 0);

  if (send_count_flag != 0)
  {
    std::cout << "发送循环次数: " << count << std::endl;

    // 循环发送数据
    for (int x = 0; x < vect.size(); x++)
    {
      char send_buf[4096] = { 0 };

      // 发送字节序
      memcpy(send_buf, &vect[x], sizeof(message));
      int send_flag = send(sock, send_buf, sizeof(send_buf), 0);
      if (send_flag != 0)
      {
        char recv_buf[32] = { 0 };
        recv(sock, recv_buf, sizeof(recv_buf), 0);
        std::cout << "发送完成,接收状态码: " << recv_buf << std::endl;
      }
    }
  }

  closesocket(sock);
  WSACleanup();
  return 0;
}

至此读者可分别编译并运行服务端与客户端,此时会看到如下图所示的结构体输出;

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/acaf6a13.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1096627.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ 引用()的超详细解析(小白必看系列)

目录 一、前言 二、引用的概念介绍 三、引用的五大特性 &#x1f4a6; 引用在定义时必须初始化 &#x1f4a6; 一个变量可以有多个引用 &#x1f4a6; 一个引用可以继续有引用 &#x1f4a6; 引用一旦引用一个实体&#xff0c;再不能引用其他实体 &#x1f4a6; 可以对任何…

02-spring源码概述-debug流程

文章目录 1. 两个主要ApplicationContext的类继承结构图1.1 ClassPathXmlApplicationContext1.2 ClassPathXmlApplicationContext 2. DefaultListableBeanFactory类继承结构图 1. 两个主要ApplicationContext的类继承结构图 1.1 ClassPathXmlApplicationContext 1.2 ClassPath…

基于SSM的旅游景点管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

MySQL数据库——SQL优化(3/3)-limit 优化、count 优化、update 优化、SQL优化 小结

目录 limit 优化 count 优化 概述 count用法 update 优化 SQL优化 小结 limit 优化 在数据量比较大时&#xff0c;如果进行limit分页查询&#xff0c;在查询时&#xff0c;越往后&#xff0c;分页查询效率越低。 当在进行分页查询时&#xff0c;如果执行limit 2000000,1…

11 | JpaRepository 如何自定义

EntityManager 介绍 Java Persistence API 规定&#xff0c;操作数据库实体必须要通过 EntityManager 进行&#xff0c;而我们前面看到了所有的 Repository 在 JPA 里面的实现类是 SimpleJpaRepository&#xff0c;它在真正操作实体的时候都是调用 EntityManager 里面的方法。…

Java中的正则表达式

1、体验正则表达式 import java.util.regex.Matcher; import java.util.regex.Pattern;/*** Description: 体验正则表达式:提取英文单词* Author: yangyongbing* CreateTime: 2023/10/16 08:38* Version: 1.0*/ public class Regexp {public static void main(String[] args)…

【Bug】ERROR ResizeObserver loop completed with undelivered notifications.

【Bug】ERROR ResizeObserver loop completed with undelivered notifications. 报错如下&#xff1a; ERROR ResizeObserver loop completed with undelivered notifications.at handleError (webpack-internal:///./node_modules/webpack-dev-server/client/overlay.js:299…

Qt 视口和窗口的区别

视口和窗口 绘图设备的物理坐标是基本的坐标系&#xff0c;通过QPainter的平移、旋转等变换可以得到更容易操作的逻辑坐标 为了实现更方便的坐标&#xff0c;QPainter还提供了视口(Viewport)和窗口(Window)坐标系&#xff0c;通过QPainter内部的坐标变换矩阵自动转换为绘图设…

802.1x协议详解,802协议工作原理/认证过程、MAB认证、EAP报文格式

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 802.1x协议 1、什么是802.1x协议2、802.1x架构3、触…

【LeetCode热题100】-- 45.跳跃游戏II

45.跳跃游戏II 方法&#xff1a;贪心 在具体的实现中&#xff0c;维护当前能够到达的最大下标的位置&#xff0c;记为边界。从左到右遍历数组&#xff0c;到达边界时&#xff0c;更新边界并将跳跃次数加一 在遍历数组时&#xff0c;不访问最后一个元素&#xff0c;因为在访问…

命令的历史管理

查看历史命令 cat ~/.bash_history history 清除历史命令 history -c >~/.bash_history 指定命令清除历史命令 history -d 55 vim /etc/profile 修改source /etc/profile (保存修改内容)

麒零8000S到底是7纳米还是14纳米?一切都因台积电玩坏了工艺命名

日本分析机构在拆解了国产5G手机对5G芯片进行扫描后&#xff0c;认为它的工艺只有14纳米&#xff0c;而一些专家则认为这是7纳米&#xff0c;导致如此混乱的原因在于台积电玩坏了芯片工艺的命名规则。 在16纳米之前&#xff0c;芯片制造企业是以栅极间距来认定芯片工艺的&#…

车联网场景中 JT/T 808 协议终端免开发快速接入阿里云 IoT 物联网平台实战

车联网场景中 JT/T 808协议 是一种在中国广泛应用的车载终端通信协议&#xff0c;用于车辆与监控中心之间的数据通信。 01 JT/T808 协议 JT/T808 协议是指交通部颁布的《道路运输车辆卫星定位系统终端通讯协议及数据格式》&#xff0c;广泛应用于车辆远程监管、物流管理、车辆安…

基于SpringBoot+vue的汽车销售管理系统

文章目录 项目介绍主要功能截图&#xff1a;登录首页新订单客户管理添加库存车辆库存管理报表管理员工管理 部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简…

LLM Tech Map 大模型技术图谱

LLM Tech Map 大模型技术图谱 从基础设施、大模型、Agent、AI 编程、工具和平台&#xff0c;以及算力几个方面&#xff0c;为开发者整理了当前 LLM 中最为热门和硬核的技术领域以及相关的软件产品和开源项目。 核心价值&#xff1a;帮助技术人快速了解 LLM 的核心技术和关键方向…

Java毕业设计基于springboot+vue的影视信息网站

项目介绍 影城管理系统的主要使用者分为管理员和用户&#xff0c;实现功能包括管理员&#xff1a;首页、个人中心、用户管理、电影类型管理、放映厅管理、电影信息管理、购票统计管理、系统管理、订单管理&#xff0c;用户前台&#xff1a;首页、电影信息、电影资讯、个人中心…

块链串的实现(c语言)

串有三种三种顺序串&#xff0c;链式串和块链式串 常用的是第一种顺序串 前两者我在这就不进行讲解了&#xff0c;因为就是普通的顺序表和链式表只是其中的值必须是字符而已 为啥需要引入块链式串&#xff0c;我们之前分析过链表的优点是操作方便&#xff0c;而缺点是&#x…

USB协议学习(一)帧格式以及协议抓取

USB协议学习&#xff08;一&#xff09;帧格式以及协议抓取 笔者来聊聊MPU的理解 这里写自定义目录标题 USB协议学习&#xff08;一&#xff09;帧格式以及协议抓取MPU的概念以及作用MPU的配置新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式…

数据挖掘(5)分类数据挖掘:基于距离的分类方法

一、分类挖掘的基本流程 最常用的就是客户评估 1.1分类器概念 1.2分类方法 基于距离的分类方法决策树分类方法贝叶斯分类方法 1.3分类的基本流程 步骤 建立分类模型 通过分类算法对训练集训练&#xff0c;得到有指导的学习、有监督的学习预定义的类&#xff1a;类标号属性确定…

【UE4 材质编辑篇】1.0 shader编译逻辑

UE4新手&#xff0c;学起来&#xff08;&#xff09;文章仅记录自己的思考。 参考&#xff1a;虚幻4渲染编程(材质编辑器篇)【第一卷&#xff1a;开篇基础】 - 知乎 (zhihu.com) 开篇基础就摸不着头脑&#xff0c;原因是此前完全没有摸过UE4&#xff0c;一点一点记录吧&#x…