超级好用的C++实用库之套接字

💡 需要该C++实用库源码的大佬们,可搜索微信公众号“希望睿智”。添加关注后,输入消息“超级好用的C++实用库”,即可获得源码的下载链接。

概述

        C++中的Socket编程是实现网络通信的基础,允许程序通过网络与其他程序交换数据。但Socket编程在Windows和Linux系统上存在一些差异,主要包括如下几点。

        1、Linux涉及网络编程的头文件主要为<sys/socket.h>、<netinet/in.h>、<arpa/inet.h>,Windows上的头文件主要为<winsock2.h>。

        2、Linux不需要显式初始化和清理操作,Windows需要使用WSAStartup和WSACleanup进行显式初始化和清理操作。

        3、Linux通常使用perror()或检查返回值,错误码直接从系统调用返回。Windows一般使用WSAGetLastError()获取错误码,并通过WSASetLastError()设置错误码。

        4、Linux使用标准的POSIX数据类型,比如:socklen_t。Windows需要使用特定的类型,比如用SOCKET代替int作为套接字描述符。

        新手对以上这些差异不熟悉的话,往往会遇到各种各样的问题。另外,阻塞与非阻塞方式发送和接收数据,接口的使用方式也是完全不一样的。为了屏蔽这些差异,并提供更加易用的接口,我们封装了CHP_Socket类。

CHP_Socket

        CHP_Socket类是一个接口类,不需要实例化。因此,我们将构造函数和析构函数声明成了私有的,并提供了若干实用的静态函数。这些静态函数涵盖全局初始化、全局清理、初始化TCP套接字、非阻塞连接、非阻塞发送、非阻塞接收等各种操作。

        CHP_Socket类的头文件,可参考下面的示例代码。

#pragma once#ifdef _WIN32#include <winsock2.h>
#else#include <unistd.h>
#endif#include "HP_Types.h"#define HP_SOCKET_E_GENERAL                           -1
#define HP_SOCKET_E_NOROUTE                           -2
#define HP_SOCKET_E_UNREACHABLE                       -3
#define HP_SOCKET_E_NOSERVER                          -4
#define HP_SOCKET_E_TIMEOUT                           -5
#define HP_SOCKET_E_WOULDBLOCK                        1
#define HP_SOCKET_E_ATLEAST_ONE_BYTE                  2#ifdef _WIN32#define  HP_SOCKET_INVALID_HANDLE             INVALID_SOCKETtypedef SOCKET HP_SOCKET;
#else#define  HP_SOCKET_INVALID_HANDLE             -1typedef int HP_SOCKET;
#endifclass CHP_Socket
{
public:static int Startup();static int Cleanup();static HP_SOCKET InitTcp(unsigned int uiRecvBufSize = 0, unsigned int uiSendBufSize = 0, bool bNoBlock = true);static HP_SOCKET InitUdp(unsigned int uiRecvBufSize = 0, unsigned int uiSendBufSize = 0, bool bNoBlock = true);static void Deinit(HP_SOCKET &sock);static int SetLinger(HP_SOCKET sock, bool bLinger, unsigned int uiTimeoutSec);static int EnableNoBlock(HP_SOCKET sock, bool bEnable = true);static int EnableReuseAddr(HP_SOCKET sock, bool bEnable = true);static int EnableBroadcast(HP_SOCKET sock, bool bEnable = true);static int SetOption(HP_SOCKET sock, int nOptionName, char *pOption, int nOptionLen);static int GetOption(HP_SOCKET sock, int nOptionName, char *pOption, int &nOptionLen);static int Bind(HP_SOCKET sock, unsigned int uiIP, unsigned short usPort);static int Bind(HP_SOCKET sock, const char *pszIP, unsigned short usPort);static int Listen(HP_SOCKET sock, int nListenNum);static int Accept(HP_SOCKET sock, HP_SOCKET &sockNew);static int Connect(HP_SOCKET sock, unsigned int uiIP, unsigned short usPort);static int Connect(HP_SOCKET sock, const char *pszIP, unsigned short usPort);static int ProbeConnect(HP_SOCKET sock);static int TcpSendSingle(HP_SOCKET sock, char *pBuf, int &nBufLen);static int TcpSendWhole(HP_SOCKET sock, char *pBuf, int nTotalLen, int &nSendedLen);static int TcpSendTimeout(HP_SOCKET sock, char *pBuf, int nBufLen, unsigned int uiTimeoutSec);static int TcpRecvSingle(HP_SOCKET sock, char *pBuf, int &nBufLen);static int TcpRecvWhole(HP_SOCKET sock, char *pBuf, int nTotalLen, int &nRecvedLen);static int TcpRecvWholeUntilKey(HP_SOCKET sock, char *pBuf, int nTotalLen, int &nRecvedLen, const char *pszKey);static int TcpRecvTimeout(HP_SOCKET sock, char *pBuf, int nBufLen, unsigned int uiTimeoutSec);static int UdpSend(HP_SOCKET sock, char *pBuf, int &nBufLen, unsigned int uiIP, unsigned short usPort);static int UdpSend(HP_SOCKET sock, char *pBuf, int &nBufLen, const char *pszIP, unsigned short usPort);static int UdpRecv(HP_SOCKET sock, char *pBuf, int &nBufLen, unsigned int &uiIP, unsigned short &usPort);static int UdpRecv(HP_SOCKET sock, char *pBuf, int &nBufLen, char pszIP[16], unsigned short &usPort);static int GetRemoteAddr(HP_SOCKET sock, unsigned int &uiIP, unsigned short &usPort);static int GetRemoteAddr(HP_SOCKET sock, char pszIP[16], unsigned short &usPort);static int GetLocalAddr(HP_SOCKET sock, unsigned int &uiIP, unsigned short &usPort);static int GetLocalAddr(HP_SOCKET sock, char pszIP[16], unsigned short &usPort);static char *IPUintToStr(unsigned int uiIP, char pszIP[16]);static unsigned int IPStrToUint(const char *pszIP);static unsigned short HostToNetwork(unsigned short usValue);static unsigned int HostToNetwork(unsigned int uiValue);static HP_U64 HostToNetwork(HP_U64 ui64Value);static unsigned short NetworkToHost(unsigned short usValue);static unsigned int NetworkToHost(unsigned int uiValue);static HP_U64 NetworkToHost(HP_U64 ui64Value);static int BindDevice(HP_SOCKET sock, const char *pszNetName = "eth0");private:static int SetRecvBufSize(HP_SOCKET sock, unsigned int uiSize);static int SetSendBufSize(HP_SOCKET sock, unsigned int uiSize);static int PasreErrorCode(int nErrorCode);static int Select(HP_SOCKET sock, unsigned int uiTimeoutSec, bool bCheckWrite);private:CHP_Socket();~CHP_Socket();
};

        在头文件的开头部分,我们定义几个错误码。其中,小于0的值表示遇到了错误,大于0的值表示非阻塞模式下未发送完或接收完所有数据。各个错误码具体的含义如下。

        HP_SOCKET_E_GENERAL:通用错误。

        HP_SOCKET_E_NOROUTE:网络不可达。

        HP_SOCKET_E_UNREACHABLE:主机不可达。

        HP_SOCKET_E_NOSERVER:服务器拒绝。

        HP_SOCKET_E_TIMEOUT:连接超时或收发数据超时。

        HP_SOCKET_E_WOULDBLOCK:未连接上,需要继续等待;或未收到数据,需要继续等待;或数据未发送出去,需要继续等待。

        HP_SOCKET_E_ATLEAST_ONE_BYTE:收到或者发送了至少一个字节的数据。

        接下来,我们将详细介绍CHP_Socket类导出的公共接口。

        Startup:全局初始化,应用层在程序开始调用一次即可。返回值为0表示成功,其他为错误码。

        Cleanup:全局清理,应用层在程序结束调用一次即可。返回值为0表示成功,其他为错误码。

        InitTcp:初始化TCP套接字。参数uiRecvBufSize为接收缓冲区大小,单位为B,传0默认为8KB。参数uiSendBufSize为发送缓冲区大小,单位为B,传0默认为8KB。参数bNoBlock表示是否设置非阻塞模式。成功返回套接字,失败返回HP_SOCKET_INVALID_HANDLE。

        InitUdp:初始化UDP套接字,参数与返回值的含义同上。

Deinit:释放socket。参数sock为待释放的套接字,可以是TCP套接字,也可以是UDP套接字。

        SetLinger:设置socket的SO_LINGER参数(Windows不支持该接口,会直接返回错误)。参数sock为需要设置的套接字,参数bLinger表示是否启用延迟关闭,参数uiTimeoutSec为延迟关闭的时间,单位为秒。返回值为0表示成功,其他为错误码。

        EnableNoBlock:使能socket的非阻塞模式。参数sock为需要设置的套接字,参数bEnable表示是否使能非阻塞模式。返回值为0表示成功,其他为错误码。

        EnableReuseAddr:使能socket重复绑定。参数sock为需要设置的套接字,参数bEnable表示是否使能重复绑定。返回值为0表示成功,其他为错误码。

        EnableBroadcast:使能socket发送广播信息。参数sock为需要设置的套接字,参数bEnable表示是否使能发送广播信息。返回值为0表示成功,其他为错误码。

        SetOption:调用setsockopt设置socket的SOL_SOCKET选项。参数sock为需要设置的套接字,参数snOptionName为选项名称,具体参考setsockopt的optname参数定义。参数pOption为选项值内容,具体参考setsockopt的optvalue参数定义。参数nOptionLen为选项值内容长度,具体参考setsockopt的optlen参数定义。返回值为0表示成功,其他为错误码。

        GetOption:调用getsockopt获取socket的SOL_SOCKET选项,参数与返回值的含义同上。

        Bind:绑定socket的本地地址。参数sock为需要设置的套接字,参数uiIP或pszIP为绑定的IP地址(网络字节序整数或字符串),参数usPort为绑定的端口。返回值为0表示成功,其他为错误码。

        Listen:监听socket的连接。参数sock为需要设置的套接字,参数nListenNum为请求队列的最大连接数。返回值为0表示成功,其他为错误码。

        Accept:接受客户端的连接请求。参数sock为已经监听的套接字,参数sockNew为请求连接的客户端套接字,用于传出。返回值为0表示成功,其他为错误码。

        Connect:连接指定的服务器地址。参数sock为需要连接的套接字,参数uiIP或pszIP为需要连接的服务器IP地址(网络字节序整数或字符串),参数usPort为需要连接的服务器端口。返回值为0表示连接成功,HP_SOCKET_E_WOULDBLOCK表示正在连接,需要调用ProbeConnect不断探测,其他为错误码。

        ProbeConnect:非阻塞模式下探测连接服务器是否成功。参数sock为需要探测连接的套接字。返回值为0表示连接成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续探测,其他为错误码。

        TcpSendSingle:TCP连接发送数据。参数sock为需要发送数据的套接字,参数pBuf为需要发送的数据,参数nBufLen传入时为需要发送数据的长度,传出时为已经发送的数据长度。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续发送,其他为错误码。

        TcpSendWhole:tcp连接发送数据,可以从上次已发送的位置继续发送数据。参数sock为需要发送数据的套接字,参数pBuf为需要发送的数据,参数nTotalLen为需要发送数据的总长度,参数nSendedLen传入时为已经发送数据的长度,传出时为最新已经发送的数据长度。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续发送,HP_SOCKET_E_ATLEAST_ONE_BYTE表示发送了至少一个字节的数据,也需要继续发送,其他为错误码。

        TcpSendTimeout:TCP连接在指定的超时时间内发送数据。参数sock为需要发送数据的套接字,参数pBuf为需要发送的数据,参数nBufLen为需要发送数据的长度,参数uiTimeoutSec为指定的超时时间,单位为秒。返回值为0表示成功,其他为错误码。

        TcpRecvSingle:TCP连接接收数据。参数sock为需要接收数据的套接字,参数pBuf为接收数据的缓存,参数nBufLen传入时为需要接收的数据长度,传出时为已经接收到数据的长度。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续接收,其他为错误码。

        TcpRecvWhole:TCP连接接收数据,可以从上次已接收的位置继续接收数据。参数sock为需要接收数据的套接字,参数pBuf为接收数据的缓存,参数nTotalLen为接收数据的总长度,参数nRecvedLen传入时为缓存中已经接收的数据长度,传出时为最新已经接收的数据长度。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续接收,HP_SOCKET_E_ATLEAST_ONE_BYTE表示收到了至少一个字节的数据,也需要继续接收,其他为错误码。

        TcpRecvWholeUntilKey:TCP连接接收数据直到指定的字符串为止。参数sock为需要接收数据的套接字,参数pBuf为接收数据的缓存,参数nTotalLen为接收数据的总长度,参数nRecvedLen传入时为缓存中已经接收的数据长度,传出时为最新已经接收的数据长度,参数pszKey为指定的结束字符串,一般用于接收指定的边界。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续接收,HP_SOCKET_E_ATLEAST_ONE_BYTE表示收到了至少一个字节的数据,也需要继续接收,其他为错误码。

        TcpRecvTimeout:TCP连接在指定的超时时间内接收数据。参数sock为需要接收数据的套接字,参数pBuf为接收数据的缓存,参数nBufLen为接收数据的长度,参数uiTimeoutSec为指定的超时时间,单位为秒。返回值为0表示成功,其他为错误码。

        UdpSend: UDP连接发送数据。参数sock为需要发送数据的套接字,参数pBuf为需要发送的数据,参数nBufLen为传入需要发送数据的长度,返回已经发送数据的长度,参数uiIP或pszIP为发送目标的IP地址(网络字节序整数或字符串),参数usPort为发送目标的端口。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续发送,其他为错误码。

        UdpRecv:UDP连接接收数据。参数sock为需要接收数据的套接字,参数pBuf为接收数据的缓存,参数nBufLen传入时为需要接收的数据长度,传出时为已经接收到数据的长度。参数uiIP或pszIP返回接收数据的来源IP地址(网络字节序整数或字符串),参数usPort返回接收数据的来源端口。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续接收,其他为错误码。

        GetRemoteAddr:获取套接字的对端IP地址和端口。参数sock为需要获取的套接字,参数uiIP或pszIP表示返回的IP地址(网络字节序整数或字符串),参数usPort表示返回的端口。返回值为0表示成功,其他为错误码。

        GetLocalAddr:获取套接字本地绑定的IP地址和端口,参数与返回值的含义同上。

        IPUintToStr:将整数型IP地址(网络字节序)转换成字符串型IP地址。参数uiIP为整数型IP地址(网络字节序),参数pszIP为字符串型IP地址,用于传出。返回值为字符串型IP地址,非NULL表示成功,否则失败。

        IPStrToUint:将字符串型IP地址转换成整数型IP地址(网络字节序)。参数pszIP为字符串型IP地址,返回值为整数型IP地址(网络字节序),非0表示成功,否则失败。

        HostToNetwork:将主机字节序转换成网络字节序,可以是16位无符号整数、32位无符号整数、64位无符号整数。

        NetworkToHost:将网络字节序转换成主机字节序,可以是16位无符号整数、32位无符号整数、64位无符号整数。

        BindDevice:将套接字绑定到某个设备(该接口仅对Linux有效),该接口一般用于多卡绑定同时发送数据。参数sock为套接字,参数pszNetName为设备的网卡接口名称,默认为"eth0"。返回值为0表示成功,其他为错误码。

总结

        Socket编程是实现网络间进程通信的基础技术之一,掌握它等于掌握了网络通信的“语言”。无论是简单的数据传输、文件共享,还是复杂的分布式系统构建,Socket都是不可或缺的知识点。了解Socket编程的底层机制,有助于开发者对网络应用的性能瓶颈进行定位和优化,比如:通过调整缓冲区大小、使用非阻塞IO或异步IO模型等方式提升数据传输效率。

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

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

相关文章

【基础篇-Day8:JAVA字符串的学习】

目录 1、常用API2、String类2.1 String类的特点2.2 String类的常见构造方法2.3 String类的常见面试题&#xff1a;2.3.1 面试题一&#xff1a;2.3.2 面试题二&#xff1a;2.3.3 面试题三&#xff1a;2.3.4 面试题四&#xff1a; 2.4 String类字符串用于比较的方法2.5 String类字…

埃隆·马斯克的 xAI 募集 60 亿美元,瞄准 AI 超级计算机|TodayAI

埃隆马斯克&#xff08;Elon Musk&#xff09;创立的人工智能公司 xAI 宣布成功募集了 60 亿美元的资金&#xff0c;用于推动其“首批产品推向市场&#xff0c;建立先进的基础设施&#xff0c;并加速未来技术的研发”。马斯克透露&#xff0c;xAI 目前的估值已达到 180 亿美元&…

css 中box-shadow使用总结

还记得我之前还是 ie 时代的时候我们如果遇到有投影&#xff0c;阴影的设计稿&#xff0c;一般的做法就是使用图片作为背景实现&#xff0c;如果要是做自适应宽高还需要利用好几个元素拼接起来设置图片背景实现&#xff0c;而现在我们想要实现投影只需要一个 css 属性 box-shad…

如何简化不同网间文件摆渡的操作流程,降低IT人员工作量?

为了保护内部核心数据不被泄露&#xff0c;同时有效屏蔽外部网络攻击的风险&#xff0c;企业大多会选择实施网络隔离。将“自己人”与“外人”隔离&#xff0c;具有较强的安全敏感性。有些企业还会在内部网络中进一步划分&#xff0c;比如划分为研发网、办公网、生产网等&#…

PaliGemma – 谷歌的最新开源视觉语言模型(一)

引言 PaliGemma 是谷歌推出的一款全新视觉语言模型。该模型能够处理图像和文本输入并生成文本输出。谷歌团队发布了三种类型的模型&#xff1a;预训练&#xff08;PT&#xff09;模型、混合&#xff08;Mix&#xff09;模型和微调&#xff08;FT&#xff09;模型&#xff0c;每…

Vue3实战笔记(48)— reactive大揭秘:Vue 3中复杂数据结构的响应式处理

文章目录 前言reactive 的基本用法1、创建响应式对象&#xff1a;2、在模板中使用响应式对象&#xff1a;3、响应式对象的嵌套&#xff1a; 总结 前言 前些天了解了ref&#xff0c;开发时候大部分时候都是直接用ref&#xff0c;其实还有reactive这玩意&#xff0c;有时候用起来…

C语言实现正弦信号扫频

C语言实现正弦信号扫频 包含必要的头文件:首先,你需要包含 <stdio.h> 和 <math.h> 头文件,分别用于输入输出和数学函数的使用。 定义扫频参数:定义正弦扫频的参数,例如起始频率、结束频率、扫频时间等。 生成正弦波信号:使用正弦函数生成扫频信号,可以根…

【Django】从零开始学Django【2】

五. CBV视图 Django植入了视图类这一功能&#xff0c;该功能封装了视图开发常用的代码&#xff0c;无须编写大量代码即可快速完成数据视图的开发&#xff0c;这种以类的形式实现响应与请求处理称为CBV(Class Base Views)。 1. 数据显示视图 数据显示视图是将后台的数据展示…

C语言 static extern 关键字详解

1、建立2个文件&#xff1b;文件1&#xff1a;file1.c // 文件&#xff1a;counter.c#include <stdio.h>static int count 0; // 声明一个静态全局变量void increment() {count; // 对静态全局变量进行递增操作 } static int n_function() //int n_function() {printf(…

LED屏控制卡是如何控制LED屏的?

LED屏控制卡是LED显示屏的关键组件之一&#xff0c;负责将输入的画面信息转换为LED屏能够显示的数据和控制信号。以下是LED屏控制卡的工作原理和功能的详细介绍&#xff1a; 1. LED显示屏控制器概述&#xff1a; LED显示屏控制器是LED显示屏的核心部件之一&#xff0c;也称为LE…

记一次Chanakya靶机的渗透测试

Chanakya靶机渗透测试 首先通过主机发现发现到靶机的IP地址为:172.16.10.141 然后使用nmap工具对其进行扫描:nmap -sC -sV -sS -p- 172.16.10.141 发现目标靶机开启了80,22,21等多个端口&#xff0c; 访问80端口,发现是一个普通的页面,点击进入多个界面也没有其他有用的信息,然…

前端面试题12-22

12 Proxy是什么&#xff0c;有什么作用&#xff1f; Proxy 是 ES6 (ECMAScript 2015) 引入的一种元编程特性。它允许你创建一个对象&#xff0c;该对象可以拦截和定义基本操作&#xff08;例如属性查找、赋值、枚举、函数调用等&#xff09;。Proxy 提供了一种机制&#xff0c…

Openai革新AI陪伴赛道?国内的AI陪伴创业公司有哪些?

人是一切社会关系的总和&#xff0c;而人的这种社会关系又依靠着情感来联系的。但是自从陪伴式AI的出现仿佛就打破了这种传统的关系。 在你的身边有这样一个“人”&#xff0c;她善解人意、风趣幽默&#xff0c;不会发脾气还会随时陪伴着你&#xff0c;这一在科幻电影中才会出现…

Linux-----sed案例练习

1.数据准备 准备数据如下&#xff1a; [rootopenEuler ~]# cat openlab.txt My name is jock. I teach linux. I like play computer game. My qq is 24523452 My website is http://www.xianoupeng.com My website is http://www.xianoupeng.com My website is http://www.…

解决linux kernel 编译的错误问题

linux 这么大的工程&#xff0c;当你的模块和别人的模块公用一个框架比如DRM 祖爷爷级别的Makefile 给你规定了 -Werrorincompatible-pointer-types 这个时候你又不想用它怎么办呢 就是在你的代码里加上 #pragma GCC diagnostic ignored "-Wincompatible-pointer-types&…

AI作画算法原理

AI作画算法原理详解如下&#xff1a; 一、引言 AI作画是指利用人工智能算法生成图像或绘画的技术。近年来&#xff0c;随着深度学习技术的突破&#xff0c;AI作画已取得了令人瞩目的成果。这些算法能够模拟人类艺术家的创作过程&#xff0c;生成具有艺术性和创意性的图像。 …

振弦采集仪在岩土工程地质灾害监测中的可行性研究

振弦采集仪在岩土工程地质灾害监测中的可行性研究 引言&#xff1a; 岩土工程地质灾害是指在岩土体中由于自然力和人类活动等因素引起的&#xff0c;对人类生活、财产以及环境造成威胁的灾害。为了及时发现并准确监测地质灾害的发生和演化过程&#xff0c;振弦采集仪作为一种新…

计网期末复习指南:物理层(物理层的任务、香农公式、常用信道复用技术)

前言&#xff1a;本系列文章旨在通过TCP/IP协议簇自下而上的梳理大致的知识点&#xff0c;从计算机网络体系结构出发到应用层&#xff0c;每一个协议层通过一篇文章进行总结&#xff0c;本系列正在持续更新中... 计网期末复习指南&#xff08;一&#xff09;&#xff1a;计算机…

零基础想学编程,选择哪一门语言更好?(非常详细)零基础入门到精通就业,收藏这一篇就够了!

&#x1f446;点击关注 获取更多编程干货&#x1f446; 编程语言的用途广泛&#xff0c;它们各自在不同的领域和应用场景中发挥着重要作用。 零基础初学者在选择编程语言时&#xff0c;可以从就业方向入手选择。 Python 就业方向&#xff1a;数据科学、机器学习、人工智能…

基于 IP 的 DDOS 攻击实验

介绍 基于IP的分布式拒绝服务&#xff08;Distributed Denial of Service, DDoS&#xff09;攻击是一种利用大量受控设备&#xff08;通常是僵尸网络&#xff09;向目标系统发送大量请求或数据包&#xff0c;以耗尽目标系统的资源&#xff0c;导致其无法正常提供服务的攻击方式…