转载:http://www.cnblogs.com/-Lei/archive/2012/09/04/2670942.html
以前写的,现在回顾一下:
下面是对socket操作的封装,因为在Linux下写中文到了windows里面会乱码,所以注释用英文来写,有空再查下解决方法吧
socket.h
#ifndef SOCKET_H #define SOCKET_H#include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string>const int MAXCONNECTION=5; const int MAXRECEIVE = 500;class Socket {public:Socket();//virtual destructiorvirtual ~Socket();// Server initializationbool Create(); //create a socketbool Bind(const int port);bool Listen() const;bool Accept(Socket& clientSocket) const;// Client initializationbool Connect(const std::string& host,const int port);// Data Transmissionbool Send(Socket& socket,const std::string& message) const;int Receive(Socket& socket,std::string& message) const;void SetNonBlocking(const bool flag);bool IsValid() const;private://use m_sockfd to record the result of function socketint m_sockfd;struct sockaddr_in m_address; };#endif
这里解释下为什么析构函数是虚的,如果要用到多态的话,也就是用一个指向基类的指针来处理对不同到对象
如果类的成员函数不是虚函数,只是个普通的函数,那么会出现一种静态绑定到情况,如
Base* pBase = new Derive; //这里Base的析构函数不是虚函数
delete pBase; //这里只会调用Base::~Base(),所以派生类部分的资源将得不到释放
如果析构函数是虚函数的话,那么将调用Derive::~Derive(),由于我们提供了派生类的析构函数,编译器会扩展这个析构函数,
在里面调用基类的析构函数,这样派生类和基类的资源都将得到释放
socket.cpp
#include "Socket.h" #include <stdlib.h> #include <memory.h> #include <iostream> #include <fcntl.h>Socket::Socket() :m_sockfd(-1) { }Socket::~Socket() {if(IsValid())::close(m_sockfd); }//server function bool Socket::Create() {m_sockfd=socket(AF_INET,SOCK_STREAM,0);if(!IsValid())return false;return true; }bool Socket::Bind(const int port) {if(!IsValid())return false;m_address.sin_family=AF_INET;m_address.sin_addr.s_addr = htonl(INADDR_ANY);m_address.sin_port=htons(port);int bindReturn=bind(m_sockfd,(struct sockaddr*)&m_address,sizeof(m_address));if(bindReturn==-1)return false;return true; }bool Socket::Listen()const {if(!IsValid())return false;int listenReturn=listen(m_sockfd,MAXCONNECTION);if(listenReturn ==-1)return false;return true; }bool Socket::Accept(Socket& clientSocket) const {int clientaddrLength=sizeof(clientSocket.m_address);clientSocket.m_sockfd=::accept(m_sockfd,(struct sockaddr*)&clientSocket.m_address,(socklen_t *)&clientaddrLength);if(clientSocket.m_sockfd==-1)return false;return true; } //end server functionsbool Socket::Connect(const std::string& host,const int port) {if(!IsValid())return false;m_address.sin_family=AF_INET;m_address.sin_port=htons(port);m_address.sin_addr.s_addr=inet_addr(host.c_str());int connectReturn=::connect(m_sockfd,(struct sockaddr*)&m_address,sizeof(m_address));if(connectReturn==-1)return false;return true;}// Data Transmission bool Socket::Send(Socket& socket,const std::string& message) const {int result=::send(socket.m_sockfd,message.c_str(),message.length(),MSG_NOSIGNAL);if(result==-1)return false;return true; }int Socket::Receive(Socket& socket,std::string& message) const {char buffer[MAXRECEIVE+1];message.clear();memset(buffer,0,MAXRECEIVE+1);int numberRead=::recv(socket.m_sockfd,buffer,MAXRECEIVE,0);if(numberRead==-1){std::cout<<"error in Socket::Receive\n";return 0;}else if(numberRead==0)return 0;else{message=buffer;return numberRead;}}void Socket::SetNonBlocking(const bool flag) {if(IsValid())
{
int opts;
opts = fcntl ( m_sockfd,
F_GETFL );
if ( opts < 0 )
{
return;
}
if ( flag )
opts = ( opts | O_NONBLOCK );
else
opts = ( opts & ~O_NONBLOCK );
fcntl ( m_sockfd,
F_SETFL,opts );
}
}bool Socket::IsValid() const {//if call function socket fail,it returns -1return m_sockfd!=-1; }
接下来是异常处理到类
#ifndef SocketException_H #define SocketException_H#include <string>class SocketException {public:SocketException ( std::string description ) : m_description( description ) {};~SocketException (){};std::string Description() { return m_description; }private:std::string m_description; };#endif