服务器客户端通信—类的封装
#ifndef _YFY_ADDR_H
#define _YFY_ADDR_H
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/time.h>
#include <unistd.h>
#include <errno.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <string.h>
#define DEFAULT_PORT 8890
class YFY_Addr
{
public:
YFY_Addr(int type = AF_INET, char *ip = 0, unsigned int port = DEFAULT_PORT);
void setFamily(sa_family_t );
void setPort(unsigned int port);
void setIp(const char *str_ip);
void setIp(unsigned int ip);
bool operator == (const YFY_Addr &sap) const;
bool operator !=(const YFY_Addr &sap)const;
unsigned int getPort();
void getIp(const char * str_ip);
unsigned int getSize() const;
const void *getAddr() const;
struct sockaddr * convert() const;
private:
struct sockaddr_in _addr;
};
#endif
#include "../inc/YFY_Addr.h"
YFY_Addr::YFY_Addr(int type/* = AF_INET*/, char *ip/* = 0*/, unsigned int port/* = DEFAULT_PORT*/)
{
bzero(&_addr, sizeof(_addr));
_addr.sin_family = type;
if(ip)
_addr.sin_addr.s_addr = inet_addr(ip);
else
_addr.sin_addr.s_addr = htonl(INADDR_ANY);
_addr.sin_port = htons(port);
}
void YFY_Addr::setFamily(sa_family_t family)
{
_addr.sin_family = family;
}
void YFY_Addr::setPort(unsigned int port)
{
_addr.sin_port = htons(port);
}
void YFY_Addr::setIp(const char * str_ip)
{
if(0 == str_ip || 0 == strcmp("hostname", str_ip))
_addr.sin_addr.s_addr = htonl(INADDR_ANY);
else
_addr.sin_addr.s_addr = inet_addr(str_ip);
}
void YFY_Addr::setIp(unsigned int ip)
{
_addr.sin_addr.s_addr = htonl(ip);
}
bool YFY_Addr::operator==(const YFY_Addr &sap) const
{
return 0 == memcmp(&_addr, sap.getAddr(), sap.getSize());
}
bool YFY_Addr::operator!=(const YFY_Addr &sap) const
{
return 0 != memcmp(&_addr, sap.getAddr(), sap.getSize());
}
unsigned int YFY_Addr::getSize() const
{
return sizeof(_addr);
}
const void * YFY_Addr::getAddr() const
{
return &_addr;
}
struct sockaddr * YFY_Addr::convert() const
{
return (struct sockaddr *)&_addr;
}
#ifndef _YFY_SOCKET_H
#define _YFY_SOCKET_H
#include <sys/types.h>
#include <sys/socket.h>
#include "YFY_Addr.h"
class YFY_Socket
{
public:
int setOption(int level, int opt_type, const void *optval, socklen_t optlen);
int getOption(int level, int opt_type, void *optval, socklen_t *optlen);
int close();
int getFileDescriptor();
void setFileDescriptor(int sock);
int getLocalAddr(YFY_Addr &) const;
int getRemoteAddr(YFY_Addr &) const;
protected:
YFY_Socket();
~YFY_Socket();
protected:
int _sockfd;
};
#endif
#include "../inc/YFY_Socket.h"
YFY_Socket::YFY_Socket()
{
}
YFY_Socket::~YFY_Socket()
{
}
void YFY_Socket::setFileDescriptor(int sock)
{
_sockfd = sock;
}
int YFY_Socket::getFileDescriptor()
{
return _sockfd;
}
int YFY_Socket::setOption(int level, int opt_type, const void * optval, socklen_t optlen)
{
setsockopt(_sockfd, level, opt_type, optval, optlen);
}
int YFY_Socket::getOption(int level, int opt_type, void * optval, socklen_t * optlen)
{
getsockopt(_sockfd, level, opt_type, optval, optlen);
}
int YFY_Socket::close()
{
return ::close(_sockfd);
}
int YFY_Socket::getLocalAddr(YFY_Addr & addr) const
{
struct sockaddr_in local_addr;
socklen_t addrlen;
if(0 == getsockname(_sockfd, (struct sockaddr *)&local_addr, &addrlen))
{
addr.setFamily(local_addr.sin_family);
addr.setIp(local_addr.sin_addr.s_addr);
addr.setPort(local_addr.sin_port);
}
}
int YFY_Socket::getRemoteAddr(YFY_Addr & addr) const
{
struct sockaddr_in peer_addr;
socklen_t addrlen;
if(0 == getpeername(_sockfd, (struct sockaddr *)&peer_addr, &addrlen))
{
addr.setFamily(peer_addr.sin_family);
addr.setIp(peer_addr.sin_addr.s_addr);
addr.setPort(peer_addr.sin_port);
}
}
#ifndef _YFY_SOCK_ACCEPTOR_H
#define _YFY_SOCK_ACCEPTOR_H
#include "YFY_Addr.h"
#include "YFY_Tcp_Socket.h"
class YFY_Sock_Acceptor
{
public:
YFY_Sock_Acceptor(YFY_Tcp_Socket * sock = 0);
~YFY_Sock_Acceptor();
int open(YFY_Addr * addr);
void setSocket(YFY_Tcp_Socket *sock = 0);
YFY_Tcp_Socket *accept();
private:
YFY_Tcp_Socket *_sock;
YFY_Addr * _addr;
};
#endif
#include "../inc/YFY_Sock_Acceptor.h"
YFY_Sock_Acceptor::YFY_Sock_Acceptor(YFY_Tcp_Socket * sock/* = 0*/)
{
_sock = sock;
}
YFY_Sock_Acceptor::~YFY_Sock_Acceptor()
{
}
int YFY_Sock_Acceptor::open(YFY_Addr *addr)
{
_addr = addr;
if(0 != bind(_sock->getFileDescriptor(), addr->convert(), addr->getSize()))
return -1;
if(0 != listen(_sock->getFileDescriptor(), 1))
return -1;
return 0;
}
void YFY_Sock_Acceptor::setSocket(YFY_Tcp_Socket * sock/* = 0*/)
{
_sock = sock;
}
YFY_Tcp_Socket * YFY_Sock_Acceptor::accept()
{
int peer_fd;
unsigned int addr_len;
YFY_Tcp_Socket *nsock = 0;
peer_fd = ::accept(_sock->getFileDescriptor(), _addr->convert(), &addr_len);
if(-1 == peer_fd)
return 0;
nsock = new YFY_Tcp_Socket(peer_fd);
return nsock;
}
#ifndef _YFY_SOCK_CONNECTOR_H
#define _YFY_SOCK_CONNECTOR_H
#include "../inc/YFY_Addr.h"
#include "../inc/YFY_Time_Value.h"
#include "../inc/YFY_Tcp_Socket.h"
class YFY_Sock_Connector
{
public:
YFY_Sock_Connector();
~YFY_Sock_Connector();
/*non-block*/
int connect(YFY_Addr & serv_addr, YFY_Tcp_Socket &serv_sock, YFY_Time_Value *time = 0);
};
#endif
#include "../inc/YFY_Sock_Connector.h"
YFY_Sock_Connector::YFY_Sock_Connector()
{
}
YFY_Sock_Connector::~YFY_Sock_Connector()
{
}
int YFY_Sock_Connector::connect(YFY_Addr & serv_addr, YFY_Tcp_Socket & serv_sock, YFY_Time_Value * timeout/* = 0*/)
{
int flags;
int sockfd;
int n;
int error;
int result;
socklen_t len;
fd_set rset, wset;
struct timeval tvalue;
sockfd = serv_sock.getFileDescriptor();
if(!timeout)
return ::connect(sockfd, serv_addr.convert(), serv_addr.getSize());
else
{
flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
result = ::connect(sockfd, serv_addr.convert(), serv_addr.getSize());
if(result != EINPROGRESS)
return -1;
if(0 == result)
return 0;
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
wset = rset;
tvalue.tv_sec = timeout->getSec();
tvalue.tv_usec = timeout->getUsec();
n = select(sockfd + 1, &rset, &wset, NULL, &tvalue);
if(!n)
{
serv_sock.close();
return -1;
}
if(FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset))
{
len = sizeof(error);
if(serv_sock.getOption(SOL_SOCKET, SO_ERROR, &error, &len) < 0)
return -1;
}
else
return -1;
fcntl(sockfd, F_SETFL, flags);
if(error)
{
serv_sock.close();
return -1;
}
return 0;
}
}
#ifndef _YFY_TCP_SOCKET_H
#define _YFY_TCP_SOCKET_H
#include "../inc/YFY_Time_Value.h"
#include "../inc/YFY_Socket.h"
class YFY_Tcp_Socket : public YFY_Socket
{
public:
YFY_Tcp_Socket();
YFY_Tcp_Socket(int sockfd);
~YFY_Tcp_Socket();
int recv(void *buff, unsigned int nbytes, int flags, YFY_Time_Value *timeout = 0);
int send(const void *buff, unsigned int nbytes, int flags);
int readv(const struct iovec *iov, int iovcnt , YFY_Time_Value *timeout = 0);
int writev(const struct iovec *iov, int iovcnt);
int recvMsg(struct msghdr * msg, int flags, YFY_Time_Value *timeout = 0);
int sendMsg(struct msghdr * msg, int flags);
};
#endif
#include "../inc/YFY_Tcp_Socket.h"
YFY_Tcp_Socket::YFY_Tcp_Socket()
{
_sockfd = socket(AF_INET, SOCK_STREAM, 0);
}
YFY_Tcp_Socket:: YFY_Tcp_Socket(int sockfd)
{
setFileDescriptor(sockfd);
}
YFY_Tcp_Socket::~YFY_Tcp_Socket()
{
}
int YFY_Tcp_Socket::recv(void *buff, unsigned int nbytes, int flags, YFY_Time_Value *timeout/* = 0*/)
{
int sockfd;
int retval;
socklen_t len;
fd_set rset;
struct timeval tvalue;
sockfd = _sockfd;
if(!timeout)
return ::recv(sockfd, buff, nbytes, flags);
else
{
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
tvalue.tv_sec = timeout->getSec();
tvalue.tv_usec = timeout->getUsec();
retval= select(sockfd + 1, &rset, NULL, NULL, &tvalue);
if (retval == -1)
return -1;
else if (retval)
{
if(FD_ISSET(sockfd, &rset))
return ::recv(sockfd, buff, nbytes, flags);
else
return 0;
}
else
return 0;
}
}
int YFY_Tcp_Socket::send(const void * buff, unsigned int nbytes, int flags)
{
return ::send(_sockfd, buff, nbytes, flags);
}
int YFY_Tcp_Socket::readv(const struct iovec * iov, int iovcnt, YFY_Time_Value *timeout/* = 0*/)
{
int sockfd;
int retval;
socklen_t len;
fd_set rset;
struct timeval tvalue;
sockfd = _sockfd;
if(!timeout)
return ::readv(sockfd, iov, iovcnt);
else
{
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
tvalue.tv_sec = timeout->getSec();
tvalue.tv_usec = timeout->getUsec();
retval= select(sockfd + 1, &rset, NULL, NULL, &tvalue);
if (retval == -1)
return -1;
else if (retval)
{
if(FD_ISSET(sockfd, &rset))
return ::readv(sockfd, iov, iovcnt);
else
return 0;
}
else
return 0;
}
}
int YFY_Tcp_Socket::writev(const struct iovec * iov, int iovcnt)
{
return ::writev(_sockfd, iov, iovcnt);
}
int YFY_Tcp_Socket::recvMsg(struct msghdr * msg, int flags, YFY_Time_Value *timeout/* = 0*/)
{
int sockfd;
int retval;
socklen_t len;
fd_set rset;
struct timeval tvalue;
sockfd = _sockfd;
if(!timeout)
return ::recvmsg(sockfd, msg,flags);
else
{
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
tvalue.tv_sec = timeout->getSec();
tvalue.tv_usec = timeout->getUsec();
retval= select(sockfd + 1, &rset, NULL, NULL, &tvalue);
if (retval == -1)
return -1;
else if (retval)
{
if(FD_ISSET(sockfd, &rset))
return ::recvmsg(sockfd, msg,flags);
else
return 0;
}
else
return 0;
}
}
int YFY_Tcp_Socket::sendMsg(struct msghdr * msg, int flags)
{
return ::sendmsg(_sockfd, msg, flags);
}
#ifndef _YFY_UDP_SOCKET_H
#define _YFY_UDP_SOCKET_H
#include "YFY_Socket.h"
#include "YFY_Time_Value.h"
#include "YFY_Addr.h"
class YFY_Udp_Socket:public YFY_Socket
{
public:
YFY_Udp_Socket();
~YFY_Udp_Socket();
int readv(const struct iovec *iov, int iovcnt , YFY_Time_Value *timeout = 0);
int writev(const struct iovec *iov, int iovcnt);
int recvFrom(void *buf, size_t len, int flags, YFY_Addr *src_addr);
int sendTo(const void *buf, size_t len, int flags, YFY_Addr *dest_addr);
};
#endif
#include "../inc/YFY_Udp_Socket.h"
YFY_Udp_Socket::YFY_Udp_Socket()
{
}
YFY_Udp_Socket::~YFY_Udp_Socket()
{
}
int YFY_Udp_Socket::readv(const struct iovec *iov, int iovcnt , YFY_Time_Value *timeout/* = 0*/)
{
int sockfd;
int retval;
socklen_t len;
fd_set rset;
struct timeval tvalue;
sockfd = _sockfd;
if(!timeout)
return ::readv(sockfd, iov, iovcnt);
else
{
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
tvalue.tv_sec = timeout->getSec();
tvalue.tv_usec = timeout->getUsec();
retval= select(sockfd + 1, &rset, NULL, NULL, &tvalue);
if (retval == -1)
return -1;
else if (retval)
{
if(FD_ISSET(sockfd, &rset))
return ::readv(sockfd, iov, iovcnt);
else
return 0;
}
else
return 0;
}
}
int YFY_Udp_Socket::writev(const struct iovec * iov, int iovcnt)
{
return ::writev(YFY_Socket::_sockfd, iov, iovcnt);
}
int YFY_Udp_Socket::recvFrom(void *buf, size_t len, int flags, YFY_Addr *src_addr)
{
unsigned int addrlen = src_addr->getSize();
return ::recvfrom(_sockfd, buf, len, flags, src_addr->convert(), &addrlen);
}
int YFY_Udp_Socket::sendTo(const void *buf, size_t len, int flags, YFY_Addr *dest_addr)
{
return ::sendto(_sockfd, buf, len, flags, dest_addr->convert(), dest_addr->getSize());
}
#ifndef _YFY_TIME_VALUE_H
#define _YFY_TIME_VALUE_H
class YFY_Time_Value
{
public:
YFY_Time_Value(unsigned int sec = 0, unsigned int usec = 0);
~YFY_Time_Value();
unsigned int getSec();
unsigned int getUsec();
void setSec(unsigned int sec);
void setUsec(unsigned int usec);
public:
unsigned int _sec;
unsigned int _usec;
};
#endif
#include "../inc/YFY_Time_Value.h"
YFY_Time_Value::YFY_Time_Value(unsigned int sec/* = 0*/, unsigned int usec/* = 0*/)
{
_sec = sec;
_usec = usec;
}
YFY_Time_Value::~YFY_Time_Value()
{
}
unsigned int YFY_Time_Value::getSec()
{
return _sec;
}
unsigned int YFY_Time_Value::getUsec()
{
return _usec;
}
void YFY_Time_Value::setSec(unsigned int sec)
{
_sec = sec;
}
void YFY_Time_Value::setUsec(unsigned int usec)
{
_usec = usec;
}
#include "YFY_Client.h"
#include <stdio.h>
int main(int argc, char * argv[])
{
YFY_Tcp_Socket peer;
YFY_Sock_Connector connector;
YFY_Addr peer_addr;
char message[200];
int n;
peer_addr.setIp("hostname");
peer_addr.setPort(DEFAULT_PORT);
if(0 == connector.connect(peer_addr, peer))
{
n = peer.recv(message, 200, 0);
printf("%s\n", message);
peer.send("my name is YFY_Client", strlen("my name is YFY_Client"), 0);
peer.close();
}
}
#include "YFY_Server.h"
#include <stdio.h>
int main(int argc, char *argv[])
{
YFY_Addr server_addr;
YFY_Sock_Acceptor acceptor;
YFY_Tcp_Socket *peer;
YFY_Tcp_Socket serv_sock;
char message[200];
int optval = 1;
int optlen = sizeof(optval);
server_addr.setIp("hostname");
server_addr.setPort(DEFAULT_PORT);
serv_sock.setOption(SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
acceptor.setSocket(&serv_sock);
if(acceptor.open(&server_addr))
{
printf("bind or listen error\n");
return 0;
}
if(peer = acceptor.accept())
{
peer->send("welcome to server", strlen("welcome to server"), 0);
peer->recv(message, 200, 0);
peer->close();
}
}