以前寫的,現在回顧一下:
下面是對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 destructior virtual ~Socket(); // Server initialization bool Create(); //create a socket bool Bind(const int port); bool Listen() const; bool Accept(Socket& clientSocket) const; // Client initialization bool Connect(const std::string& host,const int port); // Data Transmission bool 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 socket int 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 functions bool 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 -1 return 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