首先为什么要实行分块传输字符串,一般而言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 字符串分块传输的更多相关文章

  1. atitit.二进制数据无损转字符串网络传输

    atitit.二进制数据无损转字符串网络传输 1. gbk的网络传输问题,为什么gbk不能使用来传输二进制数据 1 2. base64 2 3. iso-8859-1  (推荐) 2 4. utf-8 ...

  2. HTTP分块传输

    HTTP分块传输 用途 对于在发送HTTP头部前,无法计算出Content-Length的HTTP请求及回复(例如WEB服务端产生的动态内容),可以使用分块传输,使得不至于等待所有数据产生后,再发送带 ...

  3. 洗礼灵魂,修炼python(86)--全栈项目实战篇(12)—— 利用socket实现文件传输/并发式聊天

    由于本篇博文的项目都很简单,所以本次开个特例,本次解析两个项目,但是都很简单的 项目一:用socket实现文件传输 本项目很简单,作为小项目的预热的,前面刚学完socket,这里马上又利用socket ...

  4. Burpsuit分块传输插件绕WAF原理和技巧(转)

      0x00 原理 给服务器发送payload数据包,使得waf无法识别出payload,当apache,tomcat等web容器能正常解析其内容.如图一所示 0x02  实验环境 本机win10+x ...

  5. HTTP 响应的分块传输

    Transfer-Encoding 响应头用于告诉客户端服务器发送内容的编码格式. 其可选值有: chunked:数据分块发送.此时应缺省 Content-Length 响应头. compress:使 ...

  6. 利用分块传输吊打所有WAF--学习笔记

    在看了bypassword的<在HTTP协议层面绕过WAF>之后,想起了之前做过的一些研究,所以写个简单的短文来补充一下文章里“分块传输”部分没提到的两个技巧. 技巧1 使用注释扰乱分块数 ...

  7. HTTP 笔记与总结(9)分块传输、持久链接 与 反向 ajax(comet / server push / 服务器推技术)

    反向 ajax 又叫 comet / server push / 服务器推技术 应用范围:网页聊天服务器,例如新浪微博在线聊天.google mail 网页聊天 原理:一般而言,HTTP 协议的特点是 ...

  8. java socket 多线程网络传输多个文件

    http://blog.csdn.net/njchenyi/article/details/9072845 java socket 多线程网络传输多个文件 2013-06-10 21:26 3596人 ...

  9. Python Cookbook(第3版)中文版:15.14 传递Unicode字符串给C函数库

    15.14 传递Unicode字符串给C函数库¶ 问题¶ 你要写一个扩展模块,需要将一个Python字符串传递给C的某个库函数,但是这个函数不知道该怎么处理Unicode. 解决方案¶ 这里我们需要考 ...

  10. JAVA之旅(三十二)——JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用

    JAVA之旅(三十二)--JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用 GUI写到一半电脑系统挂了,也就算了,最多GUI还有一个提示框和实例, ...

随机推荐

  1. 解决ttrss(Tiny Tiny RSS)中fever无法使用的问题

    问题描述 在ttrss刚搭建好的时候,进行了如下操作: 随后键入了密码(fever密码) 最后,按照官方给的提示,在Fluent Reader中测试,弹出如下错误信息: 解决方案 复制官方给的链接,删 ...

  2. 【scikit-learn基础】--『监督学习』之 谱聚类

    谱聚类算法基于图论,它的起源可以追溯到早期的图分割文献.不过,直至近年来,受益于计算机计算能力的提升,谱聚类算法才得到了广泛的研究和关注. 谱聚类被广泛应用于图像分割.社交网络分析.推荐系统.文本聚类 ...

  3. POJ - 1113 Wall (凸包模板) Graham Scan 算法实现

    Description Once upon a time there was a greedy King who ordered his chief Architect to build a wall ...

  4. GPT应用开发:GPT插件开发指南

    欢迎阅读本系列文章!我将带你一起探索如何利用OpenAI API开发GPT应用.无论你是编程新手还是资深开发者,都能在这里获得灵感和收获. 本文,我们将继续展示聊天API中插件的使用方法,让你能够轻松 ...

  5. 响应式开发bootstrap

    响应式开发原理 就是使用媒体查询针对不同宽度的设备进行布局和样式的设置,从而适配不同设备的目的. 平时我们响应式尺寸划分 超小屏幕(手机,小于768px):设置宽度为100% 小屏幕(平板,大于等于7 ...

  6. lucene.net全文检索(二)lucene.net 的封装

    查询 public class LuceneQuery : ILuceneQuery { #region Identity private Logger logger = new Logger(typ ...

  7. Git Clone一个GitHub仓库时,发生报错

    1.问题 1.使用HTTP方式:Git: fatal: unable to access ' https://github. com/Light-City/CPlusPlusThings. git/' ...

  8. RSA趣题篇(简单型)

    1.n与p的关系 题目 ('n=', 288990088827100766680640490138486855101396196362885475612662192799072729620922966 ...

  9. Security的一些配置

    package com.example.demo.config; import com.example.demo.Service.UserDetailsServiceImpl; import com. ...

  10. 【ES系列】(一)简介与安装

    首发博客地址 首发博客地址 系列文章地址 教学视频 为什么要学习 ES? 强大的全文搜索和检索功能:Elasticsearch 是一个开源的分布式搜索和分析引擎,使用倒排索引和分布式计算等技术,提供了 ...