首页 > 其他分享 >14.3 Socket 字符串分块传输

14.3 Socket 字符串分块传输

时间:2023-10-13 09:04:08浏览次数:33  
标签:Socket 14.3 分块 int char Split 100 数据包 服务端

首先为什么要实行分块传输字符串,一般而言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个数据包即可完成数据的发送;

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

标签:Socket,14.3,分块,int,char,Split,100,数据包,服务端
From: https://www.cnblogs.com/LyShark/p/17761058.html

相关文章

  • socket网络编程
    Socket网络编程一、计算机网络概述1、IP地址的概念IP地址就是标识网络中设备的一个地址,好比现实生活中的家庭住址。网络设备的效果图:2、IP地址的表现形式说明:IP地址分为两类:IPv4和IPv6IPv4是目前使用的IP地址IPv6是未来使用的IP地址IPv4是由点分十进制组成IPv6是......
  • Unix domain socket 简介
    原文:https://www.cnblogs.com/sparkdev/p/8359028.html Unixdomainsocket又叫IPC(inter-processcommunication进程间通信)socket,用于实现同一主机上的进程间通信。socket原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIXdomainsocket......
  • 整除分块
    证明数论分块板子求$\large\sum_{i=1}^n[n/i]$,其中$n\leq10^{10}$很明显,暴力求的复杂度是$O(n)$的,需要优化其中,例$n=10$时,$[10/4]=[10/5]$是有相等的值的不妨设第一个$[n/i]=x$的数为$l$则最后一个有$[n/i]=x$的数$\larger=[\frac{n}{[n/l]}]$理由如......
  • 关于c语言操作libwebsockets示例
    第一步,安装libwebsockets库,c语言编写的,默认安装引用库,配置相应的库及路径第二步:上代码main.h ////CreatedbyAdministratoron2020/5/1.// #ifndefMEDIA_MAIN_H#defineMEDIA_MAIN_H #define boolchar volatileintexit_sig=0; #defineMAX_PAYLOAD_SIZE 10......
  • 14.2 Socket 反向远程命令行
    在本节,我们将继续深入探讨套接字通信技术,并介绍一种常见的用法,实现反向远程命令执行功能。对于安全从业者而言,经常需要在远程主机上执行命令并获取执行结果。本节将介绍如何利用_popen()函数来启动命令行进程,并将输出通过套接字发送回服务端,从而实现远程命令执行的功能。在实现......
  • linux socket地址
    socket地址://socket地址其实是一个结构体,封装端口号和IP等信息。后面的socket相关的API需要使用到这个socket地址。//客户端  -->  服务器(IP  、Port)通用socket地址:socket网络编程接口中表示socket地址是结构体sockaddr,其定义如下:(IPv4......
  • 封装利用libwebsockets写出的客户端、服务端程序为客户端服务端类
    1.封装我们后续将使用c++来开发程序,因此有必要将用c写成的wss客户端、服务端程序作进一步封装,使其成为wss客户端类和服务端类,这样更便于调用。封装后的程序结构: ubuntu@ubuntu-virtual-machine:~/work/test_libwebsockets/lws_class$tree .├──client│  ├──cl......
  • 14.1 Socket 套接字编程入门
    Winsock是Windows操作系统上的套接字API,用于在网络上进行数据通信。套接字通信是一种允许应用程序在计算机网络上进行实时数据交换的技术。通过使用Windows提供的API,应用程序可以创建一个套接字来进行数据通信。这个套接字可以绑定到一个端口,以允许其他应用程序连接它。另外,Winsoc......
  • C++ libwebsockets搭建WebSocket服务端及Http客户端、服务端
    https://blog.csdn.net/fantasysolo/article/details/88908948  概念WebRTCWebRTC,名称源自网页即时通信(英语:WebReal-TimeCommunication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的API。它于2011年6月1日开源并在Google、Mozilla、Opera支持下被纳入万维网联......
  • 8种品牌PLC单片机使用Socket编程实现以太网开放式通信服务器视频教程
    8种品牌PLC单片机使用Socket编程实现以太网开放式通信服务器视频教程一、罗克韦尔ABMicro850系列PLC实现ModbusTCP以太网通信协议​服务器视频教程:罗克韦尔ABMicro850系列PLC做ModbusTCP以太网通信服务器、以太网调试助手和ModbusPoll调试助手做ModbusTCP以太网通信客户端,......