Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >14.3 Socket 字符串分块传输

14.3 Socket 字符串分块传输

原创
作者头像
王瑞MVP
发布于 2023-10-13 00:55:13
发布于 2023-10-13 00:55:13
41900
代码可运行
举报
运行总次数:0
代码可运行

首先为什么要实行分块传输字符串,一般而言Socket套接字最长发送的字节数为8192字节,如果发送的字节超出了此范围则后续部分会被自动截断,此时将字符串进行分块传输将显得格外重要,分块传输的关键在于封装实现一个字符串切割函数,将特定缓冲区内的字串动态切割成一个个小的子块,当切割结束后会得到该数据块的个数,此时通过套接字将个数发送至服务端此时服务端在依次循环接收数据包直到接收完所有数据包之后在组合并显示即可。

14.3.1 服务端实现

对于服务端而言只需要做两步,首先等待客户端上线,当客户端上线后则服务端会通过recv()接收当前客户端内有多少数据包,当获取到该数据包数量后再以此数量作为循环条件,循环接收数据包并在接收后通过strcat将数据包进行连接,最终合并为一个缓冲区,并输出即可;

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
#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字符行,并在计算结束后首先向服务端发送数据包的数量,当服务端接收到数量后会进入等待模式,此时客户端只需要通过循环的方式发送数据包即可,当然此段代码也存在问题,没有对数据包进行严格的验证,此处读者可自行完善;

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
#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个数据包即可完成数据的发送;

本文作者: 王瑞

本文链接: https://www.lyshark.com/post/1bd4f28f.html

版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
14.7 Socket 循环结构体传输
在上述内容中笔者通过一个简单的案例给大家介绍了在套接字编程中如何传递结构体数据,本章将继续延申结构体传输,在某些时候例如我们需要传输一些当前系统的进程列表信息,或者是当前主机中的目录文件,此时就需要使用循环结构体传输功能,循环传输结构体的关键点在于,客户端发送结构体数据之前需要通过一次通信来告诉服务端需要接收的次数,当服务端接收到次数时则可利用接收计数器依次循环接收数据直到客户端完整所有数据包的发送。
王瑞MVP
2023/10/16
2360
14.7 Socket 循环结构体传输
20.5 OpenSSL 套接字RSA加密传输
RSA算法同样可以用于加密传输,但此类加密算法虽然非常安全,但通常不会用于大量的数据传输,这是因为RSA算法加解密过程涉及大量的数学运算,尤其是模幂运算(即计算大数的幂模运算),这些运算对于计算机而言是十分耗时。
王瑞MVP
2023/11/04
4080
20.5 OpenSSL 套接字RSA加密传输
14.6 Socket 应用结构体传输
当在套接字编程中传输结构体时,可以将结构体序列化为字符串(即把结构体的所有成员打包成一个字符串),然后将字符串通过套接字传输到对端,接收方可以将字符串解析为结构体,然后使用其中的成员数据。这种方法通常被称为序列化(Serialization)和反序列化(Deserialization),本章中我们可以采用将一个结构体序列化为一个纯字符串,然后将该字符串通过套接字传输给对端,当对端收到后只需要将字节序强制转换为对等的结构体指针即可实现对该结构的解析。
王瑞MVP
2023/10/16
3690
14.6 Socket 应用结构体传输
14.11 Socket 基于时间加密通信
在之前的代码中我们并没有对套接字进行加密,在未加密状态下我们所有的通信内容都是明文传输的,这种方式在学习时可以使用但在真正的开发环境中必须要对数据包进行加密,此处笔者将演示一种基于时间的加密方法,该加密方法的优势是数据包每次发送均不一致,但数据包内的内容是一致的,当抓包后会发现每次传输的数据包密文是随机变化的,但内容始终保持一致,也就是说两个拥有相同内容的数据被加密后,数据包密文不同,其主要运用了基于当前时间戳的通信机制。
王瑞MVP
2023/10/18
3900
14.11 Socket 基于时间加密通信
14.8 Socket 一收一发通信
通常情况下我们在编写套接字通信程序时都会实现一收一发的通信模式,当客户端发送数据到服务端后,我们希望服务端处理请求后同样返回给我们一个状态值,并以此判断我们的请求是否被执行成功了,另外增加收发同步有助于避免数据包粘包问题的产生,在多数开发场景中我们都会实现该功能。
王瑞MVP
2023/10/16
2920
14.8 Socket 一收一发通信
驱动开发:内核封装TDI网络通信接口
在上一篇文章《驱动开发:内核封装WSK网络通信接口》中,LyShark已经带大家看过了如何通过WSK接口实现套接字通信,但WSK实现的通信是内核与内核模块之间的,而如果需要内核与应用层之间通信则使用TDK会更好一些因为它更接近应用层,本章将使用TDK实现,TDI全称传输驱动接口,其主要负责连接Socket和协议驱动,用于实现访问传输层的功能,该接口比NDIS更接近于应用层,在早期Win系统中常用于实现过滤防火墙,同样经过封装后也可实现通信功能,本章将运用TDI接口实现驱动与应用层之间传输字符串,结构体,多线程收发等技术。
王瑞MVP
2022/11/04
6670
驱动开发:内核封装TDI网络通信接口
20.4 OpenSSL 套接字AES加密传输
在读者了解了加密算法的具体使用流程后,那么我们就可以使用这些加密算法对网络中的数据包进行加密处理,加密算法此处我们先采用AES算法,在网络通信中,只需要在发送数据之前对特定字符串进行加密处理,而在接收到数据后在使用相同的算法对数据进行恢复即可,读者如果有了套接字编程的基础,那么理解这段代码将变得很容易。
王瑞MVP
2023/11/02
3070
20.4 OpenSSL 套接字AES加密传输
C/C++ 使用Socket模拟远程CMD
服务端(server) #include <stdio.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") //把ws2_32.lib加到Link页的连接库 #define PORT 15001 //通信的端口(指服务器端) #define ERROR 0 #define BUFFER_SIZE 1024 //注意:此Server端数据接收缓冲区 >= Clie
王瑞MVP
2022/12/28
5870
14.1 Socket 套接字编程入门
Winsock是Windows操作系统上的套接字API,用于在网络上进行数据通信。套接字通信是一种允许应用程序在计算机网络上进行实时数据交换的技术。通过使用Windows提供的API,应用程序可以创建一个套接字来进行数据通信。这个套接字可以绑定到一个端口,以允许其他应用程序连接它。另外,Winsock可以使用TCP/IP、UDP等协议来完成不同类型的数据传输任务。在网络应用程序开发中,套接字通信可以帮助应用程序开发者实现客户端/服务端模型,并实现数据的可靠传输。
王瑞MVP
2023/10/11
4680
14.1 Socket 套接字编程入门
14.10 Socket 套接字选择通信
对于网络通信中的服务端来说,显然不可能是一对一的,我们所希望的是服务端启用一份则可以选择性的与特定一个客户端通信,而当不需要与客户端通信时,则只需要将该套接字挂到链表中存储并等待后续操作,套接字服务端通过多线程实现存储套接字和选择通信,可以提高服务端的并发性能,使其能够同时处理多个客户端的请求。在实际应用场景中,这种技术被广泛应用于网络编程、互联网应用等领域。
王瑞MVP
2023/10/18
2660
14.10 Socket 套接字选择通信
驱动开发:内核封装TDI网络通信接口
在上一篇文章《驱动开发:内核封装WSK网络通信接口》中,LyShark已经带大家看过了如何通过WSK接口实现套接字通信,但WSK实现的通信是内核与内核模块之间的,而如果需要内核与应用层之间通信则使用TDK会更好一些因为它更接近应用层,本章将使用TDK实现,TDI全称传输驱动接口,其主要负责连接Socket和协议驱动,用于实现访问传输层的功能,该接口比NDIS更接近于应用层,在早期Win系统中常用于实现过滤防火墙,同样经过封装后也可实现通信功能,本章将运用TDI接口实现驱动与应用层之间传输字符串,结构体,多线程收发等技术。
王瑞MVP
2022/12/28
6550
驱动开发:内核封装TDI网络通信接口
20.6 OpenSSL 套接字分发RSA公钥
通过上一节的学习读者应该能够更好的理解RSA加密算法在套接字传输中的使用技巧,但上述代码其实并不算完美的,因为我们的公钥和私钥都必须存储在本地文本中且公钥与私钥是固定的无法做到更好的保护效果,而一旦公钥与私钥泄密则整个传输流程都将会变得不安全,最好的保护效果是RSA密钥在每次通信时都进行变换,依次来实现随机密钥对的功能。
王瑞MVP
2023/11/04
2200
20.6 OpenSSL 套接字分发RSA公钥
实战 | C++ Socket详解与研究
数据传输是病毒木马的必备技术之一,而数据回传也成为了病毒木马的一个重要特征,我们就尝试自己写一个程序来实现数据的传输,本文尝试通过c++来进行套接字(socket)的实现
HACK学习
2021/11/12
1.8K0
使用socket实现TCP和UDP传输
转载自:https://blog.csdn.net/timmiy/article/details/51946093
战神伽罗
2019/09/03
1.7K0
使用socket实现TCP和UDP传输
14.9 Socket 高效文件传输
网络上的文件传输功能也是很有必要实现一下的,网络传输文件的过程通常分为客户端和服务器端两部分。客户端可以选择上传或下载文件,将文件分块并逐块发送到服务器,或者从服务器分块地接收文件。服务器端接收来自客户端的请求,根据请求类型执行对应的操作,并根据发送的文件名或其他标识来确定要传输的文件。
王瑞MVP
2023/10/17
7130
14.9 Socket 高效文件传输
C/C++ 实现Socket交互式服务端
在 Windows 操作系统中,原生提供了强大的网络编程支持,允许开发者使用 Socket API 进行网络通信,通过 Socket API,开发者可以创建、连接、发送和接收数据,实现网络通信。本文将深入探讨如何通过调用原生网络 API 实现同步远程通信,并介绍了一个交互式 Socket 类的封装,提升了编写交互式服务器的便利性。
王瑞MVP
2023/11/25
4920
C/C++ 实现Socket交互式服务端
C++ 使用Socket实现主机间的UDP/TCP通信
服务器端的代码做了跨平台(POSIX和WINDOWS),基于POSIX平台(Linux、Mac OS X、PlayStation等)使用sys/socket.h库,windows平台使用winsock2.h库。 客户端代码因为基本都在windows运行,所以没做跨平台,需要的话你可以参考服务器端代码自己做一下。 文中写的函数原型均为windows平台,部分函数的返回类型或参数类型在POSIX会有不同。
六月丶
2023/01/01
3.1K0
C++ 使用Socket实现主机间的UDP/TCP通信
14.5 Socket 应用组播通信
组播通信是一种基于UDP协议的网络通信方式,它允许发送方将消息同时传递给多个接收方。在组播通信中,发送方和接收方都会加入一个共同的组播组,这个组播组对应一个特定的IP地址,所有加入该组播组的主机都能够接收到发送方发送的消息。组播通信可以有效地减少网络流量和网络负载,因为在传统的点对点通信方式下,每个消息都需要单独传输到每个接收方,而在组播通信中,每个消息只需要传输一次,就可以同时传递给多个接收方。
王瑞MVP
2023/10/15
4880
14.5 Socket 应用组播通信
socket基本连接
基本操作 服务端 #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <iostream> #include <string.h> int main(int argc, char* argv[]) { std::cout << "begin" << std::endl; //1.创建一个侦听socket int listenfd
opencode
2022/12/26
6720
windows环境下用c++实现socket编程
socket即套接字,用于描述地址和端口,是一个通信链的句柄。应用程序通过socket向网络发出请求或者回应。
全栈程序员站长
2022/09/14
5.2K0
windows环境下用c++实现socket编程
相关推荐
14.7 Socket 循环结构体传输
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验