14.3 Socket 字符串分块传输
首先为什么要实行分块传输字符串,一般而言Socket套接字最长发送的字节数为8192字节,如果发送的字节超出了此范围则后续部分会被自动截断,此时将字符串进行分块传输将显得格外重要,分块传输的关键在于封装实现一个字符串切割函数,将特定缓冲区内的字串动态切割成一个个小的子块,当切割结束后会得到该数据块的个数,此时通过套接字将个数发送至服务端此时服务端在依次循环接收数据包直到接收完所有数据包之后在组合并显示即可。
14.3.1 服务端实现
对于服务端而言只需要做两步,首先等待客户端上线,当客户端上线后则服务端会通过recv()接收当前客户端内有多少数据包,当获取到该数据包数量后再以此数量作为循环条件,循环接收数据包并在接收后通过strcat将数据包进行连接,最终合并为一个缓冲区,并输出即可;
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
int main(int argc, char* argv[])
{
WSADATA WSAData;
SOCKET sock, msgsock;
struct sockaddr_in ServerAddr;
if (WSAStartup(MAKEWORD(2, 0), &WSAData) != SOCKET_ERROR)
{
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(9999);
ServerAddr.sin_addr.s_addr = INADDR_ANY;
sock = socket(AF_INET, SOCK_STREAM, 0);
bind(sock, (LPSOCKADDR)&ServerAddr, sizeof(ServerAddr));
listen(sock, 10);
}
msgsock = accept(sock, (LPSOCKADDR)0, (int*)0);
// 接收需要获取的次数
char recv_count[1024] = { 0 };
recv(msgsock, recv_count, 1024, 0);
std::cout << "收包次数: " << recv_count << std::endl;
// 循环收包,并将数据包放入到此变量中
char szBuffer[8192] = { 0 };
for (int x = 0; x < atoi(recv_count); x++)
{
char Split[128] = { 0 };
recv(msgsock, Split, 100, 0);
// std::cout << "收到数据包: " << Split << std::endl;
strcat(szBuffer, Split);
}
std::cout << "完整数据包: " << szBuffer << std::endl;
closesocket(msgsock);
closesocket(sock);
WSACleanup();
return 0;
}
14.3.2 客户端实现
我们将一段长字符串进行切割每次发送100个字符,该功能的实现首先依赖于Cat函数,该函数通过传入待切割字符串指针,切割偏移以及长度,即可实现分割字符串,如下代码中通过调用Cat(szBuffer, x, 99)切割字符串,这里我们每次剪切100个字符,并将剪切后的字符依次存储到Split[y]这个缓冲区内,接着通过调用strlen()依次计算出当前有多少个100字符行,并在计算结束后首先向服务端发送数据包的数量,当服务端接收到数量后会进入等待模式,此时客户端只需要通过循环的方式发送数据包即可,当然此段代码也存在问题,没有对数据包进行严格的验证,此处读者可自行完善;
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
char* Cut(char* buffer, int offset, int length)
{
char Split[100] = { 0 };
// 每100个字符切割一次
memset(Split, 0, 100);
strncpy(Split, buffer + offset, length);
return Split;
}
int main(int argc, char* argv[])
{
WSADATA WSAData;
SOCKET sock;
struct sockaddr_in ClientAddr;
if (WSAStartup(MAKEWORD(2, 0), &WSAData) != SOCKET_ERROR)
{
ClientAddr.sin_family = AF_INET;
ClientAddr.sin_port = htons(9999);
ClientAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
sock = socket(AF_INET, SOCK_STREAM, 0);
int Ret = connect(sock, (LPSOCKADDR)&ClientAddr, sizeof(ClientAddr));
if (Ret == 0)
{
char szBuffer[8192] = "hello lyshark hello lyshark hello lyshark ";
char Split[100][1024] = { 0 };
// 每次剪切100个字符
for (int x = 0, y = 0; x < strlen(szBuffer); x += 99)
{
char* ref = Cut(szBuffer, x, 99);
strcpy(Split[y], ref);
y += 1;
}
// 计算当前有多少个100字符行
int rows = sizeof(Split) / sizeof(Split[0]);
int count = 0;
for (int x = 0; x < rows; x++)
{
if (strlen(Split[x]) != 0)
{
count += 1;
}
}
// 将发送数据包次数发送给服务端
std::cout << "发包次数: " << count << std::endl;
char send_count[1024] = { 0 };
sprintf(send_count, "%d", count);
send(sock, send_count, strlen(send_count), 0);
// 循环发送数据包
for (int x = 0; x < count; x++)
{
std::cout << "发送数据包: " << Split[x] << std::endl;
send(sock, Split[x], strlen(Split[x]), 0);
}
}
}
closesocket(sock);
WSACleanup();
Sleep(5000);
return 0;
}
运行上述程序片段,读者可看到如下图所示的输出效果,此处只需要分割8个数据包即可完成数据的发送;

14.3 Socket 字符串分块传输的更多相关文章
- atitit.二进制数据无损转字符串网络传输
atitit.二进制数据无损转字符串网络传输 1. gbk的网络传输问题,为什么gbk不能使用来传输二进制数据 1 2. base64 2 3. iso-8859-1 (推荐) 2 4. utf-8 ...
- HTTP分块传输
HTTP分块传输 用途 对于在发送HTTP头部前,无法计算出Content-Length的HTTP请求及回复(例如WEB服务端产生的动态内容),可以使用分块传输,使得不至于等待所有数据产生后,再发送带 ...
- 洗礼灵魂,修炼python(86)--全栈项目实战篇(12)—— 利用socket实现文件传输/并发式聊天
由于本篇博文的项目都很简单,所以本次开个特例,本次解析两个项目,但是都很简单的 项目一:用socket实现文件传输 本项目很简单,作为小项目的预热的,前面刚学完socket,这里马上又利用socket ...
- Burpsuit分块传输插件绕WAF原理和技巧(转)
0x00 原理 给服务器发送payload数据包,使得waf无法识别出payload,当apache,tomcat等web容器能正常解析其内容.如图一所示 0x02 实验环境 本机win10+x ...
- HTTP 响应的分块传输
Transfer-Encoding 响应头用于告诉客户端服务器发送内容的编码格式. 其可选值有: chunked:数据分块发送.此时应缺省 Content-Length 响应头. compress:使 ...
- 利用分块传输吊打所有WAF--学习笔记
在看了bypassword的<在HTTP协议层面绕过WAF>之后,想起了之前做过的一些研究,所以写个简单的短文来补充一下文章里“分块传输”部分没提到的两个技巧. 技巧1 使用注释扰乱分块数 ...
- HTTP 笔记与总结(9)分块传输、持久链接 与 反向 ajax(comet / server push / 服务器推技术)
反向 ajax 又叫 comet / server push / 服务器推技术 应用范围:网页聊天服务器,例如新浪微博在线聊天.google mail 网页聊天 原理:一般而言,HTTP 协议的特点是 ...
- java socket 多线程网络传输多个文件
http://blog.csdn.net/njchenyi/article/details/9072845 java socket 多线程网络传输多个文件 2013-06-10 21:26 3596人 ...
- Python Cookbook(第3版)中文版:15.14 传递Unicode字符串给C函数库
15.14 传递Unicode字符串给C函数库¶ 问题¶ 你要写一个扩展模块,需要将一个Python字符串传递给C的某个库函数,但是这个函数不知道该怎么处理Unicode. 解决方案¶ 这里我们需要考 ...
- JAVA之旅(三十二)——JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用
JAVA之旅(三十二)--JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用 GUI写到一半电脑系统挂了,也就算了,最多GUI还有一个提示框和实例, ...
随机推荐
- 使用port-forward本地访问k8s集群内redis
前言 通过kubectl port-forward端口转发,在本地机器上访问k8s集群内的服务/数据库,对开发.调试.定位bug都很有用. 每次都要查,这里记录一下. 步骤 当然首先要确保本地机器上安 ...
- 4个工具,让 ChatGPT 如虎添翼!
LightGBM中文文档 机器学习统计学,476页 机器学习圣经PRML中文版 经典著作<机器学习:概率视角 让 ChatGPT 如虎添翼! ChatGPT 很好用,其核心是prompt的运用, ...
- Blazor与Vue标签代码的可维护性对比
通过一个简单示例来进行对比, Vue的ElementUI组件的行内编辑: Blazor的AntDesginBlazor组件的行内编辑: 区别: el-table-column的label属性相当于Co ...
- L1-020 帅到没朋友 (20分)
当芸芸众生忙着在朋友圈中发照片的时候,总有一些人因为太帅而没有朋友.本题就要求你找出那些帅到没有朋友的人. 输入格式: 输入第一行给出一个正整数N(≤100),是已知朋友圈的个数:随后N行,每行首先给 ...
- 涂色游戏Flood-it!(IDA star算法) - HDU 4127
做题之前,可以先到下面这个网站玩一会游戏: https://unixpapa.com/floodit/?sz=14&nc=6 游戏开发里面,比较常用的一个搜索算法是寻路算法,寻路算法里面用的最 ...
- 当 Rokid 遇上函数计算
作者:王彬(阿里云解决方案架构师).姚兰天(Rokid 技术专家).聂大鹏(阿里云高级技术专家) 公司背景和业务 Rokid 创立于2014年,是一家专注于人机交互技术的产品平台公司.Rokid 通过 ...
- 三、springboot集成金仓数据库
系列导航 一.金仓数据库搭建(单机) 二.金仓数据库搭建(主从安装) 三.springboot集成金仓数据库 1.数据库中创建表 CREATE TABLE TEST_BLOCK_T ( BLOCK_I ...
- <vue 基础知识 5、事件监听>
代码结构 一. v-on基本使用 1.效果 按钮点击一下数字增加1 2.代码 01-v-on基本使用.html <!DOCTYPE html> <html lang=&quo ...
- 简易机器学习笔记(九)LeNet实例 - 在眼疾识别数据集iChallenge-PM上的应用
前言 上一节大概讲了一下LeNet的内容,这一章就直接来用,实际上用一下LeNet来进行训练和分类试试. 调用的数据集: https://aistudio.baidu.com/datasetdetai ...
- hdu 5234
题意:求在不超过k的情况下,最多可以得到多少价值. 三维dp,结合01背包,第三维就是用来保存在不同的背包容量下能得到的最大价值,也就是第三维有很多状态. #include<iostream&g ...