/Socket.h/
#ifndef _SOCKET_H_
#define _SOCKET_H_
#include "MyException.h" //异常类
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
class TCPSocket
{
protected:
TCPSocket();
virtual ~TCPSocket();
bool create();
bool bind(unsigned short int port,const char* ip=NULL)const;
bool listen(int backlog=SOMAXCONN) const;
bool accept(TCPSocket& ClientSocket)const;
bool connect(unsigned short int port,const char* ip) const;
bool reuseaddr() const;
bool isValid() const
{
return (m_sockfd!=-1);
}
public:
bool close();
int getfd() const
{
return m_sockfd;
}
bool setNonBlocking(bool flag)const;
protected:
int m_sockfd;
};
/*** TCP Client***/
class TCPClient:public TCPSocket
{
private:
struct Packet
{
unsigned int msgLen;
char text[1024];
};
public:
TCPClient(unsigned short int port,const char *ip)throw(ExceptionDerived);
TCPClient();
TCPClient(int clientfd);
~TCPClient();
size_t send(const std::string& message)const throw(ExceptionDerived);
size_t receive(std::string &message)const throw(ExceptionDerived);
size_t read(void *buf,size_t count)throw(ExceptionDerived);
void write(const void* buf,size_t count)throw(ExceptionDerived);
size_t write(const char* msg)throw(ExceptionDerived);
};
/*** TCP Server ***/
class TCPServer:public TCPSocket
{
public:
TCPServer(unsigned short int port,const char *ip=NULL,int);
~TCPServer();
void accept(TCPClient &client)const throw(ExceptionDerived);
TCPClient accept() const throw(ExceptionDerived);
};
#endif
#include "Socket.h"
TCPSocket::TCPSocket():m_sockfd(-1){}
TCPSocket::~TCPSocket()
{
if(isValid())
::close(m_sockfd);
}
bool TCPSocket::create()
{
if(isValid())
return false;
if((m_sockfd=::socket(AF_INET,SOCK_STREAM,0))==-1)
return false;
return true;
}
bool TCPSocket::bind(unsigned short int port,const char* ip)const
{
if(!isValid())
return false;
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(port);
if(ip==NULL)
addr.sin_addr.s_addr=htonl(INADDRY_ANY);
else
addr.sin_addr.s_addr=inet_addr(ip);
if(::bind(m_sockfd,(const struct sockaddr*)&addr,sizeof(addr))==-1)
return false;
return true;
}
bool TCPSocket::listen(int backlog)const
{
if(!isValid())
return false;
if(::listen(m_sockfd,backlog)==-1)
return false;
return true;
}
bool TCPSocket::accept(TCPSocket &ClientSocket)const
{
if(!isValid())
return false;
ClientSocket.m_sockfd=::accept(this->m_sockfd,NULL,NULL);
if(ClientSocket.m_sockfd==-1)
return false;
return true;
}
bool TCPSocket::connect(unsigned short int port,const char* ip)const
{
if(!isValid())
return false;
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(port);
addr.sin_addr.s_addr=inet_addr(ip);
if(::connect(m_sockfd,(const struct sockaddr*)&addr,sizeof(addr))==-1)
return false;
return true;
}
bool TCPSocket::setNonBlocking(bool flag)const
{
if(!isValid())
return false;
int opt=fcntl(m_sockfd,F_GETFL,0);
if(opt==-1)
return false;
if(flag)
opt|=O_NONBLOCK;
else
opt&=~O_NONBLOCK;
if(fcntl(m_sockfd,F_SETFL,opt)==-1)
return false;
return true;
}
bool TCPSocket::reuseaddr() const
{
if(!isValid())
return false;
int on=1;
if(setsockopt(m_sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))==-1)
return false;
return true;
}
bool TCPSocket::close()
{
if(!isValid())
return false;
::close(m_sockfd);
m_sockfd=-1;
return true;
}
/***Server TCP Socket***/
TCPServer::TCPServer(unsigned short int port,const char* ip,int backlog)throw(ExceptionDerived)
{
if(create()==false)
MY_THROW(ExceptionDerived,"tcp server create error");
if(reuseaddr()==false)
MY_THROW(ExceptionDerived,"tcp server reuseaddr error");
if(bind(port,ip)==false)
MY_THROW(ExceptionDerived,"tcp server bind error");
if(listen(backlog)==false)
MY_THROW(ExceptionDerived,"tcp server listen error");
}
TCPServer::~TCPServer(){}
void TCPServer::accept(TCPClient &client)const
throw(ExceptionDerived)
{
if(TCPSocket::accept(client)==-1)
MY_THROW(ExceptionDerived,"tcp server accept error");
}
TCPClient TCPServer::accept() const throw(ExceptionDerived)
{
TCPClient client;
if(TCPSocket::accept(client)==-1)
MY_THROW(ExceptionDerived,"tcp server accept error");
return client;
}
/*** TCP Client Socket ***/
TCPClient::TCPClient(unsigned short int port,const char* ip) throw(ExceptionDerived)
{
if(create()==false)
MY_THROW(ExceptionDerived,"tcp client create error");
if(connect(port,ip)==false)
MY_THROW(ExceptionDerived,"tcp client connect error");
}
TCPClient::~TCPClient(){}
TCPClient::TCPClient(int clientfd)
{
if(clientfd<0)
MY_THROW(ExceptionDerived,"tcp server create(parameter) error");
m_sockfd=clientfd;
}
static ssize_t readn(int fd,void *buf,size_t count);
static ssize_t writen(int fd,const void* buf,size_t count);
size_t TCPClient::send(const std::string& message)const throw(ExceptionDerieved)
{
Packet buf;
buf.msgLen=htonl(message.length());
strcpy(buf.text,message.c_str());
if(writen(m_sockfd,&buf,sizeof(buf.msgLen)+message.length())==-1)
MY_THROW(ExceptionDerived,"tcp client writen error");
return message.length();
}
size_t TCPClient::receive(std::string& message)const throw(ExceptionDerived)
{
Packet buf={0,0};
size_t readBytes=readn(m_sockfd,&buf.msgLen,sizeof(buf.msgLen));
if(readBytes==(size_t)-1)
MY_THROW(ExceptionDerived,"tcp client readn error");
else if(readBytes !=sizeof(buf.msgLen))
MY_THROW(ExceptionDerived,"perr connect closed");
unsigned int lenHost=ntohl(buf.msgLen);
readBytes=readn(m_sockfd,buf.text,lenHost);
if(readBytes==(size_t)-1)
MY_THROW(ExceptionDerived,"tcp client readn error");
else if(readBytes!=lenHost)
MY_THROW(ExceptionDerived,"peer connect error");
message=buf.text;
return message.length();
}
size_t TCPClient::read(void *buf,size_t count)throw(ExceptionDerived)
{
size_t readBytes=::read(m_sockfd,buf,count);
if(readBytes==-1)
MY_THROW(ExceptionDerived,"tcp client read error");
return (size_t)readBytes;
}
void TCPClient::write(const void *buf,size_t count)throw(ExceptionDerived)
{
if(::write(m_sockfd,buf,count)==-1)
MY_THROW(ExceptionDerived,"tcp client write error");
}
size_t TCPClient::write(const char* msg)throw(ExceptionDerived)
{
if(::write(m_sockfd,msg,strlen(msg))==-1)
MY_THROW(ExceptionDerived,"tcp client write error");
return strlen(msg);
}
static ssize_t readn(int fd,void *buf,size_t count)
{
size_t nLeft=count;
ssize_t nRead=0;
char *pBuf=(char*)buf;
while(nLeft>0)
{
if((nRead=read(fd,pBuf,nLeft))<0)
{
if(errno==EINTR)
continue;
else
return -1;
}
else if(nRead==0)
return count-nLeft;
nLeft-=nRead;
pBuf+=nRead;
}
return count;
}
static ssize_t writen(int fd,const void* buf,size_t count)
{
size_t nLeft=count;
size_t nWritten=0;
while(nLeft>0)
{
if((nWritten=write(fd,pBuf,nLeft))<0)
{
if(errno==EINTR)
continue;
else
return -1;
}
else if(nWritten==0)
continue;
nLeft-=nWritten;
pBuf+=nWritten;
}
return count;
}