尝试用C++封装Socket库

C/C++用socket实现简单的TCP文件传输 本文主要用于总结学习到的关于socket网络编程的知识以及回顾项目原理等相关内容,进一步加深了对于TCP通信与实际项目之间联系的理解,也欢迎各位大佬对于文章中的错误理解进行批评指正以及对进一步完善所需要学习了解的知识原理给出重要建议 阅读详情
这两天又看了几眼Socket编程,我老是没长性,总是东看看西看看。还老爱挑毛病,钻牛角尖,真是不可救药了。这不,又开始看Socket不顺眼了。当时是看了一个朋友给我的一段socket raw编程的代码,有一段看的我很恶心。如下:

if((ErrorCode=WSAStartup(MAKEWORD(2,1),&wsaData))!=0){
        
printf("WSAStartup failed: %d/n",ErrorCode);
        return
2;
    }
    
sockMain=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED);
    if(
sockMain==INVALID_SOCKET)
    {
        
printf("Socket failed: %d/n",WSAGetLastError());
        return
3;
    }
    
ErrorCode=setsockopt(sockMain,IPPROTO_IP,IP_HDRINCL,(char *)&flag,sizeof(int));
    if(
ErrorCode==SOCKET_ERROR)
    {
        
printf("Set sockopt failed: %d/n",WSAGetLastError());
        return
4;
    }
    
ErrorCode=setsockopt(sockMain,SOL_SOCKET,SO_SNDTIMEO,(char*)&TimeOut,sizeof(TimeOut));
    if(
ErrorCode==SOCKET_ERROR)
    {
        
printf("Set sockopt time out failed: %d/n",WSAGetLastError());
        return
5;
    }

也许很多人都觉得我神经,这个不是每个socket程序的必经之路么?要是觉得这个很难受破坏结构,那还怎么写大型的socket程序?也许吧,我说了我就是一个死脑筋,总喜欢看起来好一些东西。总觉得那种每一个函数调用后,就跟着一堆针对返回值得错误处理语句很罗嗦,为什么不用异常来使这些更优雅呢?代码上的优雅同时也就意味着代码的出错几率的降低。

再加上我对于孟岩他们所探讨的C++异常机制的怀疑还是无法深入理解。所以我打算尝试一下充分使用异常机制来完成类似上述代码得错误处理,用C++封装Winsock函数库,以后基于这个自己写的Socket C++类库,写一些通讯程序,从而暴露一些异常机制的弊病,让自己充分的理解异常机制的一些害处。现在我的理解还是太肤浅了,不够深入。

我现在的感觉是网络通讯中出现的异常简直太正常了,因为你无法预计将会发生什么,哪里会出错误,因此用异常机制去处理时非常合适的。而且我注意到很多地方的错误返回,又不少是错误发生后,确实没什么办法可以恢复的。所以,应该也不违背一些规则。试试看吧。

其实我本来是想找一个STL类似的类库,结果没找到。找到一个ACE结果把我给吓回去了,好大啊。没必要把。我只需要一个简单的用C++特性进行封装的Socket类库而已。如果有人听说了的话,请告诉我,省得我在这里白费力气。哦,不过也不白费力气,自己实现一些东西,挺好的。

我自己没读过STL代码,因此无法写出STL或者Boost风格的代码来,只能按照自我的想象,反复的调整代码了。不过通过封装一个类库,不断地debug,不断地完善,我对C++的理解一定会进一步的。也许那个时候我会说“哦?这是谁写的垃圾代码啊,简直不堪入目,愚蠢至极。。。wait,好像是我写的”然后就是羞愧至极。呵呵。

目前我实现了一个最简单的socket类库,准确说还不能叫做实现了一个类库,只能叫做用C++封装了几个socket函数而已,暂时只能叫做概念试验,但是我希望将来有一天这个能成长为一个比较简单、实用的C++ Socket类库。目前其中有3个类。
class NetException
{
public:
    
NetException();
    
NetException(const int ErrorCode);
    
NetException(const string Message, const int msgId);
    
virtual ~NetException(void);
    
string GetErrorMessage(const dword ErrorCode) const;
protected:
    
string m_Message;
    
int m_msgId;
public:

    
string getMessage(void) const
    {
        return
m_Message;
    } 

    
int getId(void) const
    {
        return
m_msgId;
    }
};

NetException类是作为我所有异常的抛出类,如果有其他库需要的话,我会将此类作为基类以继承。

class NetEnviroment
{
public:
    
NetEnviroment(void);
    
NetEnviroment(const byte bHighVersion, const byte bLowVersion);
    ~
NetEnviroment(void);
    
inline word MakeWord(const byte wHigh, const byte wLow)
    {
        return ((
word)wHigh)<<8 | wLow;
    }
    
inline word getVersion() const
    {
        return
m_wsadata.wVersion;
    }
    
inline word getHigherVersion() const
    {
        return
m_wsadata.wHighVersion;
    }
    
inline string getDescription() const
    {
        return
string(m_wsadata.szDescription);
    }
    
inline string getSystemStatus() const
    {
        return
string(m_wsadata.szSystemStatus);
    }
protected:
    
WSADATA m_wsadata;
    
bool    m_bState;
public:

    
void initial(const byte high, const byte low)
    {
        if(
WSAStartup( MakeWord(high, low), &m_wsadata ) != 0 )
            
throw NetException();
        
m_bState = true;
    }
};

NetEnviroment是作为整个Socket的环境类。凡是使用网络的程序,只需要之前放置一个NetEnviroment对象,一切就Ok了,构造函数中调用了WSAStartup。析构函数中会调用WSACleanup()。


class Socket
{
public:
    
Socket();
    
Socket(const int protocol, const int type = SOCK_STREAM, const int af = AF_INET);
    
Socket(const SOCKET s, const int protocol = IPPROTO_TCP, const int type = SOCK_STREAM, const int af = AF_INET);
    ~
Socket(void);
protected:
    
SOCKET m_socket;
    
int m_af, m_type, m_protocol, m_port;
    
SOCKADDR_IN m_remoteaddr;
    const static
int BUF_SIZE = 4096;
    
bool m_Connected;
protected:
    
void initSocket(const int protocol = IPPROTO_TCP, const int type = SOCK_STREAM, const int af = AF_INET);
public:
    
int Bind(const struct sockaddr* name, const int namelen);
    
int Bind(const word Port);
    
int Listen(const int backlog = SOMAXCONN);
    
Socket Accept(void);
    
int Connect(const string hostname, const word port);
    
int Close(void);
    
int Send(const char* buf, const int len, const int flags = 0);
    
int Send(const string message, const int flags = 0);
    
int Receive(char* buf, const int len, const int flags = 0);
    
string Receive(const int flags = 0);
    
int SendTo(const char* buf, const int len, const struct sockaddr* to, const int tolen, const int flags = 0);
    
int ReceiveFrom(char* buf, const int len, struct sockaddr* from, int* fromlen, const int flags = 0);

    
word getLocalPort(void) const;
    
struct in_addr getLocalAddress(void) const;
    
string getLocalAddressString(void) const;
    
word getRemotePort(void) const;
    
struct in_addr getRemoteAddress(void) const;
    
string getRemoteAddressString(void) const;
    
struct sockaddr_in& getSockName(SOCKET s = NULL) const;
};

ostream& operator << ( ostream& os, const Socket &s );

Socket类是真正干真家伙的类,这里面已经封装实现了很多基本的Socket函数。并且我的思想是尽量结合STL中的类型。因次我均使用STL中的string和Boost中的Regex。

基于这个类库,我写了一个获取我网站主页的代码,应该可以感觉到,代码异常简洁。

#include "NetLib.h"

NetEnviroment Env;

int main(int argc, char * argv[])
{
    
try{ 

        
Socket client;
        
client.Connect("211.157.101.207", 80);
        
client.Send("GET / HTTP/1.1/r/nHost: www.dancefires.com/r/n/r/n");
        
cout << client.Receive() << endl; 

    }
catch(NetException nerr){ 
        
cerr<< "[" << nerr.getId() << "]    " << nerr.getMessage() << endl; 
    }
}

大家可以看到,用这个类库实现TCP Client是如此的简单,Send和Receive都是string(当然我也提供了,原始的[]的接口,呵呵,不然我就无法处理二进制流了。)。

NetLib.h是我做的C++封装的Socket库的头文件。我把NetEnviroment NetEnv放在了全局变量,实际上目的是为了让程序加载时,自动初始化NetEnv,并且调用WSAStartup(),初始化Socket堆栈。

连接、发送、接收,一气呵成,看起来确实很简洁明快。一旦有错误发生,便会有异常抛出,并被捕获,然后将异常的信息输出出来。这时突然一阵嘈杂的声音:“嘿!醒醒~~醒醒,别美了~~~这可离你说的Socket类库可差远了。” 嗯,以后有时间的话,我会逐步完善。一旦具有雏形,我会放到Open source社区去让它生长。不过目前,它远算不上是一个雏形。只能算是想法。还有太多太多的事情要去做……
从零开始的C++网络编程 导语:本文主要介绍如何从零开始搭建简单的C++客户端/服务器,并进行简单的讲解和基础的压力测试演示。该文章相对比较入门,主要面向了解计算机网络但未接触过网络编程的同学。本... 阅读详情

相关推荐

C++网络编程实战:基于TCP的消息边界处理与Socket封装

网络编程中,TCP作为面向字节流的传输层协议,虽然保证了数据的可靠有序传输,但无法自动识别应用层消息边界,这导致了粘包和拆包问题。为了解决这一核心挑战,开发者需要在TCP之上设计自定义的应用层协议,常见方案包括固定长度、分隔符和头部长度字段等方法。其中,基于长度字段的TLV(Type-Length-Value)模式因其高效和灵活而被广泛采用,它通过明确的消息头定义,确保了数据的完整解析。这种底层协议设计能力是构建稳定网络应用的基础,对于理解gRPC、Redis等上层框架的通信机制至关重要。本文通过一个C++

weixin_30267785的博客 382

C++ socket 封装

C++ socket 封装

chujicainiao1989的博客 1442

c++ socket通信库

socket通信库,c++编写,只需调用几个函数即可完成socket通信过程。简单易用,C#等其他语言可调用.问题沟通可发送邮件至gaocongly@126.com

C++游戏服务器框架笔记(二)_封装Socket类

C++封装Socket类

木可的博客 7256

跨平台的最轻量级socket的c++库,支持windows,linux,solaris-cross-platform of th

跨平台的最轻量级socket的c++库,支持windows,linux,solaris-cross-platform of the most lightweight c socket library, support for Windows, Linux, Solaris

工作:三菱PLC与伺服之CC-Link IE Field Network通讯应用

CC-LINK-IE

好记性不如烂笔头 2万+

用C++封装Socket库

这两天又看了几眼Socket编程,我老是没长性,总是东看看西看看。还老爱挑毛病,钻牛角尖,真是不可救药了。这不,又开始看Socket不顺眼了。当时是看了一个朋友给我的一段socket raw编程的代码,有一段看的我很恶心。如下:if((ErrorCode=WSAStartup(MAKEWORD(2,1),&wsaData))!=0){         printf("WSAStartup fail

aa211314的专栏 3915

告别算力焦虑:手把手教你用华为CloudMatrix384超节点部署MoE大模型(附xDeepServe配置)

本文详细解析了如何在华为CloudMatrix384超节点上高效部署MoE大模型,通过xDeepServe框架配置和专家分配优化,实现2300 Tokens/s的推理吞吐。文章涵盖环境准备、性能调优、成本平衡及容灾设计,帮助开发者告别算力焦虑,提升AI推理效率。

weixin_30790841的博客 442

Socket TCP 客户端 C++动态来接库的封装

DLL的功能需要借助平台来体现,所以对于初学者建议先建立一个控制台程序来调试,并且辅以较为成熟的工具来调试能达到更好参考的效果,这次我调试的时候是以SocketTool来作为参考的这个网上有资源。的,新建一个C++控制台程序,他有现成的代码,利用SocketTool调试,然后再把代码分块封装就ok了。因为“接收”函数会阻塞,因此要实现全双工异步这种聊天效果,我选择了使用线程,以下代码是再MFC工程里的。接下来是头文件内容,建议先学会创建和引用再来尝试做这个,虽然这个也很简单。

XianLiangcheese的博客 1482

RealSense D455的标定并运行VINS-FUSION

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar

qq_40186909的博客 2万+

DeepSeek + 番茄小说:AI辅助小说开发最全指南

DeepSeek与番茄小说合作推出AI辅助小说创作系统,通过DeepSeek的文本生成能力(包括情节构建、角色塑造等)结合番茄小说的市场数据,为作者提供从创意到发布的全流程支持。系统包含智能创意生成器、角色设计、章节自动生成等核心模块,采用数据驱动优化策略,支持128K长文本处理和多风格模仿。开发架构采用Python+FastAPI技术栈,提供分层审核机制确保质量。该系统可帮助作者突破创作瓶颈,提升效率,同时提供订阅制、内容分成等多元变现模式。需注意版权问题和原创性保证。

weixin_41445009的博客 1678

C++实现Socket的工具类封装工作

在网络编程中,Socket 是最底层的通信接口,用于 TCP/UDP 的数据发送和接收。TCP(面向连接的可靠传输)适合需要可靠传输的场景,比如文件传输、HTTP 请求。保证数据顺序到达和完整性。UDP(无连接的不可靠传输)适合实时性要求高、允许丢包的场景,比如视频流、游戏状态同步。不保证顺序,也不保证数据完整。如果每次都直接调用系统 API(socket(), bind(), connect(), send(), recv() 等),代码会很零散、重复、容易出错。

ai12345678900008的博客 374

【华为Hilink SDK Linux系统开发】目录 开源一小步

目录 【华为Hilink开发】第一章:华为hilink平台简介及开发流程 【华为Hilink开发】第二章:华为hilink SDK网络适配、网关添加删除 【华为Hilink开发】第三章:华为hilink SDK子设备添加、删除 【华为Hilink开发】第四章:华为hilink SDK子设备控制及同步 【华为Hilink开发】第五章:华为hilink SDK适配遇到的问题 ...

开源一小步 3620

C++的Socket尝试

C++大作业,准备做一个即时通讯工具,查阅资料找到了Socket,迫不及待的开始了尝试,以下是我在尝试过程中遇到的一些问题,部分问题自己已经获得了答案,还有一些还不知道怎么去回答,今天就先到这里了,接下来准备去看下别人的程序,看下能否获得一些灵感。 问题1:即时通讯是样做到的?     网络分为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。通过初步的了解,IP协议对应于网络层,T

shadofight1v5的专栏 300

从零到一:QT for OpenHarmony 开发环境实战搭建与踩坑指南

本文是一份详尽的QT for OpenHarmony开发环境搭建实战指南。文章手把手教你如何在Windows和macOS系统上,从环境准备、核心工具(DevEco Studio与社区版QT SDK)安装配置,到创建首个QT Quick项目、解决构建部署中的常见问题,最终实现应用在OpenHarmony设备上运行。内容涵盖关键配置修改、资源管理及深度踩坑经验,旨在帮助开发者高效开启跨平台开发之旅。

weixin_29190573的博客 326

MFC Tab Control控件完全指南:从基础使用到高级定制

本文详细介绍了MFC中TabControl控件的使用方法和高级技巧。主要内容包括:1) TabControl基础属性设置与绑定;2) 样式定制和外观自定义;3) 创建派生类实现扩展功能;4) 动态页面管理和子对话框控制;5) 高级功能如标签拖拽排序和右键菜单。通过完整代码示例,展示了从基本应用到复杂场景的实现方案,包括多标签页管理、自定义绘制、动态添加/删除标签等核心功能,为MFC开发者提供了全面的TabControl开发指南。

专注现代C++实战,从核心语法到高性能编程,助力开发者深入掌握系统级编程精髓。 259

用streambuf简单封装socket

C++的I/O流是很强大的. 一方面在于易于使用, 类型安全. 另一方面在于容易扩展. 前几天尝试了一下用streambuf来封装客户端使用的socket. 虽然代码运行正确, 自己 的概念确实很模糊. 今天下回来cuj的光盘, 浏览了一下其中一篇也是关于使用stream来 封装socket的文章, 发现作者的概念也不比我清楚到哪里去. ;-) 先考虑一下最后客户代码的写法, 我希望是这样  

经天纬地 3975

[SV]SystemVerilog学习笔记之struct & union

SystemVerilog学习笔记(四) 一、结构体(struct) 1.1、结构体(struct) 结构体声明:结构体默认是变量,也可以声明为线网 var struct{ //通过var进行结构体变量声明 logic [31:0] a, b; logic [ 7:0] opcode; } Instruction_Word_var; wire struct{ //结构体线网声明,定义为线网类型时,结构体的所有成员必须...

元直的博客 1万+

一个比较好用的socket 类封装(封装http 请求)

 /*****************************************************************///name          : myhttp.h//function      : http 请求//copyright     : //author        : mark//date          : 2008-05-13/**********

hzhxxx的专栏 5933

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Linux C++ UDP客户端封装:从socket系统调用到面向对象设计实践

在网络编程中,UDP(用户数据报协议)作为一种无连接的传输层协议,以其低延迟和轻量级特性,在实时通信、音视频传输和游戏同步等场景中发挥着关键作用。其核心原理是通过数据包直接发送,无需建立连接,牺牲了可靠性以换取更高的传输效率。在Linux环境下,使用C++进行UDP编程通常涉及socket、bind、sendto和recvfrom等底层系统调用。通过面向对象设计封装这些调用,可以构建高内聚、低耦合的UDP客户端类,这不仅提升了代码的可维护性和复用性,还体现了RAII(资源获取即初始化)等现代C++工程实践思

weixin_30509393的博客 430

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

c++使用socket编程小demo

注意:此代码是在window平台下;linux需要自己更改部分代码,本文尽可能的使用c++标准所支持的规范来编写; 一、简单介绍socket编程所需要使用的函数 1:socket函数 int sock(int af, int type, int protocol); /* * 作用:创建一个socket * * 参数: * af: (address family)常见的一般有AF...

qq_34236354的博客 1661

Socket_cplus:构建高效网络通信的C++库

Socket_cplus:构建高效网络通信的C++库 在软件开发中,网络通信是一个至关重要的部分,尤其在分布式系统和实时应用中。Socket_cplus 是一个基于C++的轻量级、高性能的套接字库,它提供了一种简单而直接的方式来处理TCP和UDP协议,使得开发者可以更专注于业务逻辑而非底层网络操作。 项目简介 Socket_cplus 是一个C++11标准兼容的库,旨在简化网络编程的复杂性。这个项...

gitblog_00015的博客 524
上一篇: 多文件编程include规则
下一篇: 理解继承
DanceFire
博客等级 码龄26年 91粉丝 42原创
评论 16
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值