C/C++封装socket通信类
- 一、读取、写入数据
- 1、recvn函数
- 2、sendn函数
- 3、TcpRecv函数
- 4、TcpSend函数
- 二、C的封装方法
-
- 三、C++的封装方法
-
不管是socket通信程序的客户端还是服务端,准备工作的代码又长又难看占地方,影响了主程序的结构,必须分离出来。
一、读取、写入数据
1、recvn函数
bool recvn(const int sockfd, char *buffer, const size_t n) {
int remain, len, idx;
remain = n;
idx = 0;
while (remain > 0) {
if ((len = recv(sockfd, buffer + idx, remain,0)) <= 0)
return false;
idx += len;
remain -= len;
}
return true;
}
2、sendn函数
bool sendn(const int sockfd, const char *buffer, const size_t n = 0) {
int remain, len, idx;
remain = (n == 0) ? strlen(buffer) : n;
idx = 0;
while (remain > 0) {
if ((len = send(sockfd,buffer + idx, remain,0)) <= 0)
return false;
idx += len;
remain -= len;
}
return true;
}
3、TcpRecv函数
bool TcpRecv(const int sockfd,char *buffer,int *ibuflen,const int itimeout = 0) {
if (sockfd == -1) return false;
if (itimeout > 0) {
fd_set tmpfd;
FD_ZERO(&tmpfd);
FD_SET(sockfd,&tmpfd);
struct timeval timeout;
timeout.tv_sec = itimeout;
timeout.tv_usec = 0;
if (select(sockfd+1,&tmpfd,0,0,&timeout) <= 0) return false;
}
(*ibuflen) = 0;
if(!recvn(sockfd,(char*)ibuflen,4)) return false;
(*ibuflen)=ntohl(*ibuflen);
return recvn(sockfd, buffer, *ibuflen);
}
4、TcpSend函数
bool TcpSend(const int sockfd,const char *buffer,const int ibuflen = 0,const int itimeout = 5) {
if (sockfd == -1 ) return false;
if (itimeout > 0) {
fd_set tmpfd;
FD_ZERO(&tmpfd);
FD_SET(sockfd,&tmpfd);
struct timeval timeout;
timeout.tv_sec = itimeout;
timeout.tv_usec = 0;
if (select(sockfd+1,&tmpfd,0,0,&timeout) <= 0) return false;
}
int ilen = (ibuflen == 0) ? strlen(buffer) : ibuflen;
int ilenn=htonl(ilen);
char strTBuffer[ilen+4];
memset (strTBuffer,0,sizeof(strTBuffer));
memcpy (strTBuffer, &ilenn, 4);
memcpy (strTBuffer+4, buffer, ilen);
return sendn(sockfd,strTBuffer, ilen+4);
}
二、C的封装方法
C语言只能把程序代码封装成函数。
1、客户端
把客户端连接服务端的socket操作封装到connecttoserver函数中,主程序的代码更简洁。
int connecttoserver(const char *serverip,const int port) {
int sockfd = socket(AF_INET,SOCK_STREAM,0);
struct hostent* h;
if ( (h = gethostbyname(serverip)) == 0 ) {
perror("gethostbyname");
close(sockfd);
return -1;
}
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
memcpy(&servaddr.sin_addr,h->h_addr,h->h_length);
if (connect(sockfd, (struct sockaddr *)&servaddr,sizeof(servaddr)) != 0) {
perror("connect");
close(sockfd);
return -1;
}
return sockfd;
}
2、服务端
把服务端初始化socket操作封装到initserver函数中,主程序的代码更简洁。
int initserver(int port) {
int listenfd = socket(AF_INET,SOCK_STREAM,0);
int opt = 1;
unsigned int len = sizeof(opt);
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,len);
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
if (bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) != 0 ) {
perror("bind");
close(listenfd);
return -1;
}
if (listen(listenfd,5) != 0 ) {
perror("listen");
close(listenfd);
return -1;
}
return listenfd;
}
三、C++的封装方法
C++语言可以封装数据和函数,采用的是类。
1、客户端
class CTcpClient {
public:
int m_sockfd;
char m_ip[21];
int m_port;
bool m_btimeout;
int m_buflen;
CTcpClient();
bool ConnectToServer(const char *ip,const int port);
bool Recv(char *buffer,const int itimeout=0);
bool Send(const char *buffer,const int ibuflen=0,const int itimeout=5);
void Close();
~CTcpClient();
};
CTcpClient::CTcpClient() {
m_sockfd=-1;
memset(m_ip,0,sizeof(m_ip));
m_port=0;
m_btimeout=false;
}
bool CTcpClient::ConnectToServer(const char *ip,const int port) {
if (m_sockfd != -1) {
close(m_sockfd);
m_sockfd = -1;
}
strcpy(m_ip,ip);
m_port=port;
struct hostent* h;
struct sockaddr_in servaddr;
if ( (m_sockfd = socket(AF_INET,SOCK_STREAM,0) ) < 0) return false;
if ( !(h = gethostbyname(m_ip)) ) {
close(m_sockfd);
m_sockfd = -1;
return false;
}
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(m_port);
memcpy(&servaddr.sin_addr,h->h_addr,h->h_length);
if (connect(m_sockfd, (struct sockaddr *)&servaddr,sizeof(servaddr)) != 0) {
close(m_sockfd);
m_sockfd = -1;
return false;
}
return true;
}
bool CTcpClient::Recv(char *buffer,const int itimeout) {
if (m_sockfd == -1) return false;
if (itimeout>0) {
fd_set tmpfd;
FD_ZERO(&tmpfd);
FD_SET(m_sockfd,&tmpfd);
struct timeval timeout;
timeout.tv_sec = itimeout;
timeout.tv_usec = 0;
m_btimeout = false;
int i;
if ( (i = select(m_sockfd+1,&tmpfd,0,0,&timeout)) <= 0 ) {
if (i==0) m_btimeout = true;
return false;
}
}
m_buflen = 0;
return (TcpRecv(m_sockfd,buffer,&m_buflen));
}
bool CTcpClient::Send(const char *buffer,const int ibuflen,const int itimeout) {
if (m_sockfd == -1) return false;
if (itimeout>0) {
fd_set tmpfd;
FD_ZERO(&tmpfd);
FD_SET(m_sockfd,&tmpfd);
struct timeval timeout;
timeout.tv_sec = itimeout;
timeout.tv_usec = 0;
m_btimeout = false;
int i;
if ( (i = select(m_sockfd+1,&tmpfd,0,0,&timeout)) <= 0 ) {
if (i==0) m_btimeout = true;
return false;
}
}
int ilen=ibuflen;
if (ibuflen==0) ilen=strlen(buffer);
return(TcpSend(m_sockfd,buffer,ilen));
}
void CTcpClient::Close() {
if (m_sockfd > 0) close(m_sockfd);
m_sockfd=-1;
memset(m_ip,0,sizeof(m_ip));
m_port=0;
m_btimeout=false;
}
CTcpClient::~CTcpClient() {
Close();
}
2、服务端
class CTcpServer {
private:
int m_socklen;
struct sockaddr_in m_clientaddr;
struct sockaddr_in m_servaddr;
public:
int m_listenfd;
int m_connfd;
bool m_btimeout;
int m_buflen;
CTcpServer();
bool InitServer(const unsigned int port);
bool Accept();
char *GetIP();
bool Recv(char *buffer,const int itimeout=0);
bool Send(const char *buffer,const int ibuflen=0,const int itimeout=5);
void CloseListen();
void CloseClient();
~CTcpServer();
};
CTcpServer::CTcpServer() {
m_listenfd=-1;
m_connfd=-1;
m_socklen=0;
m_btimeout=false;
}
bool CTcpServer::InitServer(const unsigned int port) {
CloseListen();
if ( (m_listenfd = socket(AF_INET,SOCK_STREAM,0))<=0) return false;
int opt = 1;
unsigned int len = sizeof(opt);
setsockopt(m_listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,len);
memset(&m_servaddr,0,sizeof(m_servaddr));
m_servaddr.sin_family = AF_INET;
m_servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
m_servaddr.sin_port = htons(port);
if (bind(m_listenfd,(struct sockaddr *)&m_servaddr,sizeof(m_servaddr)) != 0 ) {
CloseListen();
return false;
}
if (listen(m_listenfd,5) != 0 ) {
CloseListen();
return false;
}
m_socklen = sizeof(struct sockaddr_in);
return true;
}
bool CTcpServer::Accept() {
if (m_listenfd == -1) return false;
if ((m_connfd=accept(m_listenfd,(struct sockaddr *)&m_clientaddr,(socklen_t*)&m_socklen)) < 0)
return false;
return true;
}
char *CTcpServer::GetIP() {
return(inet_ntoa(m_clientaddr.sin_addr));
}
bool CTcpServer::Recv(char *buffer,const int itimeout) {
if (m_connfd == -1) return false;
if (itimeout>0) {
fd_set tmpfd;
FD_ZERO(&tmpfd);
FD_SET(m_connfd,&tmpfd);
struct timeval timeout;
timeout.tv_sec = itimeout;
timeout.tv_usec = 0;
m_btimeout = false;
int i;
if ( (i = select(m_connfd+1,&tmpfd,0,0,&timeout)) <= 0 ) {
if (i==0) m_btimeout = true;
return false;
}
}
m_buflen = 0;
return(TcpRecv(m_connfd,buffer,&m_buflen));
}
bool CTcpServer::Send(const char *buffer,const int ibuflen,const int itimeout) {
if (m_connfd == -1) return false;
if (itimeout>0) {
fd_set tmpfd;
FD_ZERO(&tmpfd);
FD_SET(m_connfd,&tmpfd);
struct timeval timeout;
timeout.tv_sec = itimeout;
timeout.tv_usec = 0;
m_btimeout = false;
int i;
if ( (i = select(m_connfd+1,&tmpfd,0,0,&timeout)) <= 0 ) {
if (i==0) m_btimeout = true;
return false;
}
}
int ilen = ibuflen;
if (ilen==0) ilen=strlen(buffer);
return(TcpSend(m_connfd,buffer,ilen));
}
void CTcpServer::CloseListen() {
if (m_listenfd > 0) {
close(m_listenfd);
m_listenfd=-1;
}
}
void CTcpServer::CloseClient() {
if (m_connfd > 0) {
close(m_connfd);
m_connfd=-1;
}
}
CTcpServer::~CTcpServer() {
CloseListen();
CloseClient();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)