zio.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. #ifndef _zio_hpp_z_
  2. #define _zio_hpp_z_
  3. #ifdef _MSC_VER
  4. #include <WinSock2.h>
  5. #include <Windows.h>
  6. #else
  7. #include <unistd.h>
  8. #include <fcntl.h>
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <netinet/in.h>
  12. #include <netinet/tcp.h>
  13. #include <arpa/inet.h>
  14. #include <errno.h>
  15. #endif
  16. #include <string.h>
  17. #include <string>
  18. #include "log.h"
  19. struct zio
  20. {
  21. private:
  22. template<typename T>
  23. static int setoption(int fd,int level,int name,const T&opt)
  24. {
  25. return setsockopt(fd,level,name,(char*)&opt,sizeof(T));
  26. }
  27. static sockaddr* build_addr(sockaddr_in*addr,const char*ip,int port)
  28. {
  29. return build_addr(addr,ntohl(inet_addr(ip)),port);
  30. }
  31. static sockaddr* build_addr(sockaddr_in*addr,int ip,int port)
  32. {
  33. memset(addr, 0, sizeof(sockaddr_in));
  34. addr->sin_family = AF_INET;
  35. addr->sin_addr.s_addr = htonl(ip);
  36. addr->sin_port = htons(port);
  37. return (sockaddr*)addr;
  38. }
  39. static int bind(int fd,sockaddr*sa)
  40. {
  41. return ::bind(fd,sa,sizeof(sockaddr));
  42. }
  43. static int bind(int fd,sockaddr_in*sa)
  44. {
  45. return zio::bind(fd,(sockaddr*)sa);
  46. }
  47. static int connect(int fd,sockaddr*sa)
  48. {
  49. int rc=::connect(fd,sa,sizeof(sockaddr));
  50. if(rc<0)
  51. {
  52. char name[128];
  53. sprintf(name,"%s:%d",inet_ntoa(((sockaddr_in*)sa)->sin_addr),ntohs(((sockaddr_in*)sa)->sin_port));
  54. log_errno("zio:socket connect to %s",name);
  55. }
  56. return rc;
  57. }
  58. static int connect(int fd,sockaddr_in*sa)
  59. {
  60. return zio::connect(fd, (sockaddr*)sa);
  61. }
  62. static int bind(int fd,const char* ip,int port)
  63. {
  64. sockaddr_in si;
  65. return zio::bind(fd,build_addr(&si,ip,port));
  66. }
  67. static int bind(int fd, int inaddr,int port)
  68. {
  69. sockaddr_in si;
  70. return zio::bind(fd,build_addr(&si,inaddr,port));
  71. }
  72. static int connect(int fd,int inaddr,int port)
  73. {
  74. sockaddr_in si;
  75. return zio::connect(fd,build_addr(&si,inaddr,port));
  76. }
  77. public:
  78. static int connect(int fd,const char*ip,int port)
  79. {
  80. sockaddr_in si;
  81. return zio::connect(fd,build_addr(&si,ip,port));
  82. }
  83. static int listen(int fd,const char*ip,int port,int backlog=1024)
  84. {
  85. setnodelay(fd);
  86. setreuseaddr(fd);
  87. if(zio::bind(fd,ip,port)<0)
  88. {
  89. log_errno("zio:socket bind (%d,'%s',%d)",fd,ip,port);
  90. return -1;
  91. }
  92. return ::listen(fd,backlog);
  93. }
  94. static int setnodelay (int fd, bool nodelay = true)
  95. {
  96. int v = nodelay ? 1 : 0;
  97. return setoption (fd,IPPROTO_TCP, TCP_NODELAY, v);
  98. }
  99. static int setiobuf (int fd, int send_size,int recv_size)
  100. {
  101. if(send_size && setoption (fd, SOL_SOCKET, SO_SNDBUF, send_size)<0)
  102. {
  103. log_errno("zio:setoption(%d,SO_SNDBUF,%d)",fd,send_size);
  104. return -1;
  105. }
  106. if(recv_size && setoption (fd, SOL_SOCKET, SO_RCVBUF, recv_size)<0)
  107. {
  108. log_errno("zio:setoption(%d,SO_RECBUF,%d)",fd,recv_size);
  109. return -1;
  110. }
  111. return 0;
  112. }
  113. static int setreuseaddr (int fd, bool reuse = true)
  114. {
  115. int v = reuse ? 1 : 0;
  116. return setoption (fd, SOL_SOCKET, SO_REUSEADDR, v);
  117. }
  118. static int setrecvtimeo (int fd, int tmout_ms)
  119. {
  120. #ifdef _MSC_VER
  121. int tv = tmout_ms;
  122. #else
  123. struct timeval tv = { tmout_ms / 1000, tmout_ms % 1000 * 1000 };
  124. #endif
  125. return setoption (fd,SOL_SOCKET, SO_RCVTIMEO, tv);
  126. }
  127. static int setsendtimeo (int fd, int tmout_ms)
  128. {
  129. #ifdef _MSC_VER
  130. int tv = tmout_ms;
  131. #else
  132. struct timeval tv = { tmout_ms / 1000, tmout_ms % 1000 * 1000 };
  133. #endif
  134. return setoption (fd,SOL_SOCKET, SO_SNDTIMEO, tv);
  135. }
  136. static int setblocking (int fd, bool b=true)
  137. {
  138. #ifdef _MSC_VER
  139. #else
  140. int opts = fcntl (fd, F_GETFL);
  141. if (opts < 0)
  142. return -1;
  143. opts |= b ?(opts& ~O_NONBLOCK) :(opts|O_NONBLOCK);
  144. if (fcntl (fd, F_SETFL, opts) < 0)
  145. return -1;
  146. return 0;
  147. #endif
  148. }
  149. static int close(int fd)
  150. {
  151. if(fd==-1)
  152. return 0;
  153. #ifdef _MSC_VER
  154. return ::closesocket(fd);
  155. #else
  156. return ::close(fd);
  157. #endif
  158. }
  159. static int accept(int serv_fd,char *name)
  160. {
  161. struct sockaddr_in addr={0};
  162. int fd=-1;
  163. for(;;)
  164. {
  165. socklen_t addrlen=sizeof(struct sockaddr_in);
  166. fd=(int)::accept(serv_fd,(sockaddr*)&addr,&addrlen);
  167. if(fd<0)
  168. {
  169. #ifdef _MSC_VER
  170. #else
  171. if (errno == EINTR || errno == ECONNABORTED)
  172. continue;
  173. #endif
  174. }
  175. if(fd>=0)
  176. {
  177. sprintf(name,"%s:%d",inet_ntoa(addr.sin_addr),ntohs(addr.sin_port));
  178. log_info("zio:client %d(%s) connected",fd,name);
  179. }
  180. break;
  181. }
  182. return fd;
  183. }
  184. static int build_stream()
  185. {
  186. return (int)::socket(AF_INET,SOCK_STREAM,0);
  187. }
  188. static int write(int fd, const void *buff, int count)
  189. {
  190. const char*buf=(const char*)buff;
  191. for(;;)
  192. {
  193. int rc = ::write(fd,buf,count);
  194. if (rc == -1)
  195. {
  196. switch(errno)
  197. {
  198. #ifndef _MSC_VER
  199. case EINTR:
  200. continue;
  201. #endif
  202. case EAGAIN:
  203. #ifdef _MSC_VER
  204. case EWOULDBLOCK:
  205. #endif
  206. return -2;
  207. default:
  208. log_errno("zio:socket %d write",fd);
  209. return -1;
  210. }
  211. }
  212. return rc;
  213. }
  214. }
  215. static int read(int fd, void *buff, int count)
  216. {
  217. char*buf=(char*)buff;
  218. for(;;)
  219. {
  220. int rc = ::read(fd,buf,count);
  221. if (rc == -1)
  222. {
  223. switch(errno)
  224. {
  225. #ifndef _MSC_VER
  226. case EINTR:
  227. continue;
  228. #endif
  229. case EAGAIN:
  230. #ifdef _MSC_VER
  231. case EWOULDBLOCK:
  232. #endif
  233. return -2;
  234. default:
  235. log_errno("zio:socket %d read",fd);
  236. return -1;
  237. }
  238. }
  239. return rc;
  240. }
  241. }
  242. static int writev(int fd, const void*buff, int count)
  243. {
  244. const char*buf=(const char*)buff;
  245. int rc, pos = 0;
  246. while(pos != count)
  247. {
  248. if((rc=zio::write(fd,buf,count-pos))>0)
  249. {
  250. pos += rc;
  251. buf += rc;
  252. continue;
  253. }
  254. if(rc==-1)
  255. break;
  256. }
  257. return pos==0?-1:pos;
  258. }
  259. static int readv(int fd, void *buff, int count)
  260. {
  261. char*buf=(char*)buff;
  262. int rc, pos = 0;
  263. while(pos != count)
  264. {
  265. if((rc=zio::read(fd,buf,count-pos))>0)
  266. {
  267. pos += rc;
  268. buf += rc;
  269. continue;
  270. }
  271. if(rc==0)
  272. return pos>0?pos:0;
  273. if(rc==-1)
  274. break;
  275. }
  276. return pos==0?-1:pos;
  277. }
  278. static int listen_on(int port)
  279. {
  280. int fd=zio::build_stream();
  281. zio::setreuseaddr(fd,true);
  282. int rc=zio::listen(fd,"0.0.0.0",port,1024);
  283. if(rc<0)
  284. {
  285. zio::close(fd);
  286. return -1;
  287. }
  288. return fd;
  289. }
  290. };
  291. #endif