123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- #ifndef _zio_hpp_z_
- #define _zio_hpp_z_
- #ifdef _MSC_VER
- #include <WinSock2.h>
- #include <Windows.h>
- #else
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netinet/tcp.h>
- #include <arpa/inet.h>
- #include <errno.h>
- #endif
- #include <string.h>
- #include <string>
- #include "log.h"
- struct zio
- {
- private:
- template<typename T>
- static int setoption(int fd,int level,int name,const T&opt)
- {
- return setsockopt(fd,level,name,(char*)&opt,sizeof(T));
- }
- static sockaddr* build_addr(sockaddr_in*addr,const char*ip,int port)
- {
- return build_addr(addr,ntohl(inet_addr(ip)),port);
- }
- static sockaddr* build_addr(sockaddr_in*addr,int ip,int port)
- {
- memset(addr, 0, sizeof(sockaddr_in));
- addr->sin_family = AF_INET;
- addr->sin_addr.s_addr = htonl(ip);
- addr->sin_port = htons(port);
- return (sockaddr*)addr;
- }
- static int bind(int fd,sockaddr*sa)
- {
- return ::bind(fd,sa,sizeof(sockaddr));
- }
- static int bind(int fd,sockaddr_in*sa)
- {
- return zio::bind(fd,(sockaddr*)sa);
- }
- static int connect(int fd,sockaddr*sa)
- {
- int rc=::connect(fd,sa,sizeof(sockaddr));
- if(rc<0)
- {
- char name[128];
- sprintf(name,"%s:%d",inet_ntoa(((sockaddr_in*)sa)->sin_addr),ntohs(((sockaddr_in*)sa)->sin_port));
- log_errno("zio:socket connect to %s",name);
- }
- return rc;
- }
- static int connect(int fd,sockaddr_in*sa)
- {
- return zio::connect(fd, (sockaddr*)sa);
- }
- static int bind(int fd,const char* ip,int port)
- {
- sockaddr_in si;
- return zio::bind(fd,build_addr(&si,ip,port));
- }
- static int bind(int fd, int inaddr,int port)
- {
- sockaddr_in si;
- return zio::bind(fd,build_addr(&si,inaddr,port));
- }
- static int connect(int fd,int inaddr,int port)
- {
- sockaddr_in si;
- return zio::connect(fd,build_addr(&si,inaddr,port));
- }
- public:
- static int connect(int fd,const char*ip,int port)
- {
- sockaddr_in si;
- return zio::connect(fd,build_addr(&si,ip,port));
- }
- static int listen(int fd,const char*ip,int port,int backlog=1024)
- {
- setnodelay(fd);
- setreuseaddr(fd);
- if(zio::bind(fd,ip,port)<0)
- {
- log_errno("zio:socket bind (%d,'%s',%d)",fd,ip,port);
- return -1;
- }
- return ::listen(fd,backlog);
- }
- static int setnodelay (int fd, bool nodelay = true)
- {
- int v = nodelay ? 1 : 0;
- return setoption (fd,IPPROTO_TCP, TCP_NODELAY, v);
- }
- static int setiobuf (int fd, int send_size,int recv_size)
- {
- if(send_size && setoption (fd, SOL_SOCKET, SO_SNDBUF, send_size)<0)
- {
- log_errno("zio:setoption(%d,SO_SNDBUF,%d)",fd,send_size);
- return -1;
- }
- if(recv_size && setoption (fd, SOL_SOCKET, SO_RCVBUF, recv_size)<0)
- {
- log_errno("zio:setoption(%d,SO_RECBUF,%d)",fd,recv_size);
- return -1;
- }
- return 0;
- }
- static int setreuseaddr (int fd, bool reuse = true)
- {
- int v = reuse ? 1 : 0;
- return setoption (fd, SOL_SOCKET, SO_REUSEADDR, v);
- }
- static int setrecvtimeo (int fd, int tmout_ms)
- {
- #ifdef _MSC_VER
- int tv = tmout_ms;
- #else
- struct timeval tv = { tmout_ms / 1000, tmout_ms % 1000 * 1000 };
- #endif
- return setoption (fd,SOL_SOCKET, SO_RCVTIMEO, tv);
- }
- static int setsendtimeo (int fd, int tmout_ms)
- {
- #ifdef _MSC_VER
- int tv = tmout_ms;
- #else
- struct timeval tv = { tmout_ms / 1000, tmout_ms % 1000 * 1000 };
- #endif
- return setoption (fd,SOL_SOCKET, SO_SNDTIMEO, tv);
- }
- static int setblocking (int fd, bool b=true)
- {
- #ifdef _MSC_VER
- #else
- int opts = fcntl (fd, F_GETFL);
- if (opts < 0)
- return -1;
- opts |= b ?(opts& ~O_NONBLOCK) :(opts|O_NONBLOCK);
- if (fcntl (fd, F_SETFL, opts) < 0)
- return -1;
- return 0;
- #endif
- }
- static int close(int fd)
- {
- if(fd==-1)
- return 0;
- #ifdef _MSC_VER
- return ::closesocket(fd);
- #else
- return ::close(fd);
- #endif
- }
- static int accept(int serv_fd,char *name)
- {
- struct sockaddr_in addr={0};
- int fd=-1;
- for(;;)
- {
- socklen_t addrlen=sizeof(struct sockaddr_in);
- fd=(int)::accept(serv_fd,(sockaddr*)&addr,&addrlen);
- if(fd<0)
- {
- #ifdef _MSC_VER
- #else
- if (errno == EINTR || errno == ECONNABORTED)
- continue;
- #endif
- }
- if(fd>=0)
- {
- sprintf(name,"%s:%d",inet_ntoa(addr.sin_addr),ntohs(addr.sin_port));
- log_info("zio:client %d(%s) connected",fd,name);
- }
- break;
- }
- return fd;
- }
- static int build_stream()
- {
- return (int)::socket(AF_INET,SOCK_STREAM,0);
- }
- static int write(int fd, const void *buff, int count)
- {
- const char*buf=(const char*)buff;
- for(;;)
- {
- int rc = ::write(fd,buf,count);
- if (rc == -1)
- {
- switch(errno)
- {
- #ifndef _MSC_VER
- case EINTR:
- continue;
- #endif
- case EAGAIN:
- #ifdef _MSC_VER
- case EWOULDBLOCK:
- #endif
- return -2;
- default:
- log_errno("zio:socket %d write",fd);
- return -1;
- }
- }
- return rc;
- }
- }
- static int read(int fd, void *buff, int count)
- {
- char*buf=(char*)buff;
- for(;;)
- {
- int rc = ::read(fd,buf,count);
- if (rc == -1)
- {
- switch(errno)
- {
- #ifndef _MSC_VER
- case EINTR:
- continue;
- #endif
- case EAGAIN:
- #ifdef _MSC_VER
- case EWOULDBLOCK:
- #endif
- return -2;
- default:
- log_errno("zio:socket %d read",fd);
- return -1;
- }
- }
- return rc;
- }
- }
- static int writev(int fd, const void*buff, int count)
- {
- const char*buf=(const char*)buff;
- int rc, pos = 0;
- while(pos != count)
- {
- if((rc=zio::write(fd,buf,count-pos))>0)
- {
- pos += rc;
- buf += rc;
- continue;
- }
- if(rc==-1)
- break;
- }
- return pos==0?-1:pos;
- }
- static int readv(int fd, void *buff, int count)
- {
- char*buf=(char*)buff;
- int rc, pos = 0;
- while(pos != count)
- {
- if((rc=zio::read(fd,buf,count-pos))>0)
- {
- pos += rc;
- buf += rc;
- continue;
- }
- if(rc==0)
- return pos>0?pos:0;
- if(rc==-1)
- break;
- }
- return pos==0?-1:pos;
- }
- static int listen_on(int port)
- {
- int fd=zio::build_stream();
- zio::setreuseaddr(fd,true);
- int rc=zio::listen(fd,"0.0.0.0",port,1024);
- if(rc<0)
- {
- zio::close(fd);
- return -1;
- }
- return fd;
- }
- };
- #endif
|