分享
 
 
 

尝试用C++封装Socket库

王朝c/c++·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

这两天又看了几眼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社区去让它生长。不过目前,它远算不上是一个雏形。只能算是想法。还有太多太多的事情要去做……

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有