usocket.cpp
上传用户:chn_coc
上传日期:2007-12-20
资源大小:563k
文件大小:10k
源码类别:

P2P编程

开发平台:

Windows_Unix

  1. // ------------------------------------------------
  2. // File : lsocket.cpp
  3. // Date: 4-apr-2002
  4. // Author: giles
  5. // Desc: 
  6. // Linux version of ClientSocket. Handles the nitty gritty of actually
  7. // reading and writing TCP
  8. //
  9. // (c) 2002 peercast.org
  10. // ------------------------------------------------
  11. // This program is free software; you can redistribute it and/or modify
  12. // it under the terms of the GNU General Public License as published by
  13. // the Free Software Foundation; either version 2 of the License, or
  14. // (at your option) any later version.
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. // GNU General Public License for more details.
  19. // ------------------------------------------------
  20. // TODO: fix socket closing
  21. #include <stdio.h>
  22. #include <fcntl.h>
  23. #include <sys/ioctl.h>
  24. #include <errno.h>
  25. #include "usocket.h"
  26. #include "stats.h"
  27. #ifdef __APPLE__ 
  28. #include <netinet/in_systm.h> // for n_long definition
  29. #define MSG_NOSIGNAL 0        // doesn't seem to be defined under OS X
  30. #endif
  31. #include <netinet/ip.h>
  32. #include <netinet/tcp.h>
  33. #define INVALID_SOCKET -1
  34. #define SOCKET_ERROR -1
  35. // --------------------------------------------------
  36. void UClientSocket::init()
  37. {
  38.     LOG_DEBUG("LStartup:  OK");
  39. }
  40. // --------------------------------------------------
  41. bool ClientSocket::getHostname(char *str,unsigned int ip)
  42. {
  43. hostent *he;
  44. ip = htonl(ip);
  45. he = gethostbyaddr((char *)&ip,sizeof(ip),AF_INET);
  46. if (he)
  47. {
  48. strcpy(str,he->h_name);
  49. return true;
  50. }else
  51. return false;
  52. }
  53. // --------------------------------------------------
  54. unsigned int ClientSocket::getIP(char *name)
  55. {
  56. char szHostName[256];
  57. if (!name)
  58. {
  59. if (gethostname(szHostName, sizeof(szHostName))==0)
  60. name = szHostName;
  61. else
  62. return 0;
  63. }
  64. hostent *he = UClientSocket::resolveHost(name);
  65. if (!he)
  66. return 0;
  67. char* lpAddr = he->h_addr_list[0];
  68. if (lpAddr)
  69. {
  70. struct in_addr  inAddr;
  71. memmove (&inAddr, lpAddr, 4);
  72. return ntohl(inAddr.s_addr);
  73. }
  74. return 0;
  75. }
  76. // --------------------------------------------------
  77. void UClientSocket::setLinger(int sec)
  78. {
  79. linger linger;
  80. linger.l_onoff = (sec>0)?1:0;
  81.     linger.l_linger = sec;
  82. if (setsockopt(sockNum, SOL_SOCKET, SO_LINGER, (const char *)&linger, sizeof (linger)) == -1) 
  83. throw SockException("Unable to set LINGER");
  84. }
  85. // --------------------------------------------------
  86. void UClientSocket::setNagle(bool on)
  87. {
  88.      int nodelay = (on==false);
  89.      if (setsockopt(sockNum, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay,sizeof(nodelay)) < 0)
  90. throw SockException("Unable to set NODELAY");
  91. }      
  92. // --------------------------------------------------
  93. void UClientSocket::setBlocking(bool block)
  94. {
  95. int fl = fcntl(sockNum,F_GETFL);
  96. if (block)
  97. fl &= ~O_NONBLOCK;
  98. else
  99. fl |= O_NONBLOCK;
  100. fcntl(sockNum, F_SETFL, fl);
  101. }
  102. // --------------------------------------------------
  103. void UClientSocket::setReuse(bool yes)
  104. {
  105. unsigned long op = yes ? 1 : 0;
  106. if (setsockopt(sockNum,SOL_SOCKET,SO_REUSEADDR,(char *)&op,sizeof(op)) < 0) 
  107. throw SockException("Unable to set REUSE");
  108. }
  109. // --------------------------------------------------
  110. hostent *UClientSocket::resolveHost(char *hostName)
  111. {
  112. hostent *he;
  113. if ((he = gethostbyname(hostName)) == NULL)
  114. {
  115. // if failed, try using gethostbyaddr instead
  116. unsigned long ip = inet_addr(hostName);
  117. if (ip == INADDR_NONE)
  118. return NULL;
  119. if ((he = gethostbyaddr((char *)&ip,sizeof(ip),AF_INET)) == NULL)
  120. return NULL;
  121. }
  122. return he;
  123. }
  124. // --------------------------------------------------
  125. void UClientSocket::open(Host &rh)
  126. {
  127. sockNum = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  128. if (sockNum == INVALID_SOCKET)
  129. throw SockException("Can`t open socket");
  130. setBlocking(false);
  131. #ifdef DISABLE_NAGLE
  132. setNagle(false);
  133. #endif
  134. host = rh;
  135. memset(&remoteAddr,0,sizeof(remoteAddr));
  136. remoteAddr.sin_family = AF_INET;
  137. remoteAddr.sin_port = htons(host.port);
  138. remoteAddr.sin_addr.s_addr = htonl(host.ip);
  139. }
  140. // --------------------------------------------------
  141. void UClientSocket::checkTimeout(bool r, bool w)
  142. {
  143.     int err = errno;
  144.     if ((err == EAGAIN) || (err == EINPROGRESS))
  145.     {
  146. //LOG("checktimeout %d %d",(int)r,(int)w);
  147. timeval timeout;
  148. fd_set read_fds;
  149. fd_set write_fds;
  150. timeout.tv_sec = 0;
  151. timeout.tv_usec = 0;
  152.         FD_ZERO (&write_fds);
  153. if (w)
  154. {
  155. timeout.tv_sec = (int)this->writeTimeout/1000;
  156. FD_SET (sockNum, &write_fds);
  157. }
  158.         FD_ZERO (&read_fds);
  159. if (r)
  160. {
  161. timeout.tv_sec = (int)this->readTimeout/1000;
  162.         FD_SET (sockNum, &read_fds);
  163. }
  164. timeval *tp;
  165. if (timeout.tv_sec)
  166. tp = &timeout;
  167. else
  168. tp = NULL;
  169. int r=select (sockNum+1, &read_fds, &write_fds, NULL, tp);
  170.         if (r == 0)
  171. throw TimeoutException();
  172. else if (r == SOCKET_ERROR)
  173. throw SockException("select failed.");
  174. }else{
  175. char str[32];
  176. sprintf(str,"Closed: %s",strerror(err));
  177. throw SockException(str);
  178. }
  179. }
  180. // --------------------------------------------------
  181. void UClientSocket::checkTimeout2(bool r, bool w)
  182. {
  183.     {
  184. //LOG("checktimeout %d %d",(int)r,(int)w);
  185. timeval timeout;
  186. fd_set read_fds;
  187. fd_set write_fds;
  188. timeout.tv_sec = 0;
  189. timeout.tv_usec = 0;
  190.         FD_ZERO (&write_fds);
  191. if (w)
  192. {
  193. timeout.tv_sec = (int)this->writeTimeout/1000;
  194. FD_SET (sockNum, &write_fds);
  195. }
  196.         FD_ZERO (&read_fds);
  197. if (r)
  198. {
  199. timeout.tv_sec = (int)this->readTimeout/1000;
  200.         FD_SET (sockNum, &read_fds);
  201. }
  202. timeval *tp;
  203. if (timeout.tv_sec)
  204. tp = &timeout;
  205. else
  206. tp = NULL;
  207. int r=select (sockNum+1, &read_fds, &write_fds, NULL, tp);
  208.         if (r == 0)
  209. throw TimeoutException();
  210. else if (r == SOCKET_ERROR)
  211. throw SockException("select failed.");
  212. }
  213. }
  214. // --------------------------------------------------
  215. void UClientSocket::connect()
  216. {
  217. if (::connect(sockNum,(struct sockaddr *)&remoteAddr,sizeof(remoteAddr)) == SOCKET_ERROR)
  218. checkTimeout(false,true);
  219. }
  220. // --------------------------------------------------
  221. int UClientSocket::read(void *p, int l)
  222. {
  223. int bytesRead=0;
  224. while (l)
  225. {
  226. int r = recv(sockNum, (char *)p, l, MSG_NOSIGNAL);
  227. if (r == SOCKET_ERROR)
  228. {
  229. // non-blocking sockets always fall through to here
  230. checkTimeout(true,false);
  231. }else if (r == 0)
  232. {
  233. throw SockException("Closed on read");
  234. }else
  235. {
  236. stats.add(Stats::BYTESIN,r);
  237. if (host.localIP())
  238. stats.add(Stats::LOCALBYTESIN,r);
  239. updateTotals(r,0);
  240. bytesRead+=r;
  241. l -= r;
  242. p = (char *)p+r;
  243. }
  244. }
  245. return bytesRead;
  246. }
  247. // --------------------------------------------------
  248. int UClientSocket::readUpto(void *p, int l)
  249. {
  250. int bytesRead=0;
  251. while (l)
  252. {
  253. int r = recv(sockNum, (char *)p, l, MSG_NOSIGNAL);
  254. if (r == SOCKET_ERROR)
  255. {
  256. // non-blocking sockets always fall through to here
  257. checkTimeout(true,false);
  258. }else if (r == 0)
  259. {
  260. break;
  261. }else
  262. {
  263. stats.add(Stats::BYTESIN,r);
  264. if (host.localIP())
  265. stats.add(Stats::LOCALBYTESIN,r);
  266. updateTotals(r,0);
  267. bytesRead+=r;
  268. l -= r;
  269. p = (char *)p+r;
  270. }
  271. }
  272. return bytesRead;
  273. }
  274. // --------------------------------------------------
  275. void UClientSocket::write(const void *p, int l)
  276. {
  277. while (l)
  278. {
  279. int r = send(sockNum, (char *)p, l, MSG_DONTWAIT|MSG_NOSIGNAL);
  280. if (r == SOCKET_ERROR)
  281. {
  282. // non-blocking sockets always fall through to here
  283. checkTimeout(false,true);
  284. }else if (r == 0)
  285. {
  286. throw SockException("Closed on write");
  287. }else
  288. {
  289. stats.add(Stats::BYTESOUT,r);
  290. if (host.localIP())
  291. stats.add(Stats::LOCALBYTESOUT,r);
  292. updateTotals(0,r);
  293. l -= r;
  294. p = (char *)p+r;
  295. }
  296. }
  297. }
  298. // --------------------------------------------------
  299. void UClientSocket::bind(Host &h)
  300. {
  301. struct sockaddr_in localAddr;
  302. if ((sockNum = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
  303. throw SockException("Can`t open socket");
  304. setReuse(true);
  305. setBlocking(false);
  306. memset(&localAddr,0,sizeof(localAddr));
  307. localAddr.sin_family = AF_INET;
  308. localAddr.sin_port = htons(h.port);
  309. localAddr.sin_addr.s_addr = INADDR_ANY;
  310. if( ::bind (sockNum, (sockaddr *)&localAddr, sizeof(localAddr)) == -1)
  311. throw SockException("Can`t bind socket");
  312. if (::listen(sockNum,3))
  313. throw SockException("Can`t listen");
  314. host = h;
  315. }
  316. // --------------------------------------------------
  317. ClientSocket *UClientSocket::accept()
  318. {
  319. socklen_t fromSize = sizeof(sockaddr_in);
  320. sockaddr_in from;
  321. int conSock = ::accept(sockNum,(sockaddr *)&from,&fromSize);
  322. if (conSock ==  INVALID_SOCKET)
  323. return NULL;
  324.     UClientSocket *cs = new UClientSocket();
  325. cs->sockNum = conSock;
  326. cs->host.port = from.sin_port;
  327. cs->host.ip = ntohl(from.sin_addr.s_addr);
  328. cs->setBlocking(false);
  329. #ifdef DISABLE_NAGLE
  330. cs->setNagle(false);
  331. #endif
  332. return cs;
  333. }
  334. // --------------------------------------------------
  335. Host UClientSocket::getLocalHost()
  336. {
  337. struct sockaddr_in localAddr;
  338. socklen_t len = sizeof(localAddr);
  339.     if (getsockname(sockNum, (sockaddr *)&localAddr, &len) == 0)
  340. return Host(ntohl(localAddr.sin_addr.s_addr),0);
  341. else
  342. return Host(0,0);
  343. }
  344. // --------------------------------------------------
  345. void UClientSocket::close()
  346. {
  347. if (sockNum)
  348. {
  349. // signal shutdown
  350. shutdown(sockNum,SHUT_WR);
  351. // skip remaining data and wait for 0 from recv
  352. setReadTimeout(2000);
  353. try
  354. {
  355. //char c;
  356. //while (readUpto(&c,1)!=0);
  357. //readUpto(&c,1);
  358. }catch(StreamException &e) 
  359. {
  360. LOG_ERROR("Socket close: %s",e.msg);
  361. }
  362. // close handle
  363. ::close(sockNum);
  364. sockNum = 0;
  365. }
  366. }
  367. // --------------------------------------------------
  368. bool UClientSocket::readReady()
  369. {
  370. timeval timeout;
  371. fd_set read_fds;
  372. fd_set write_fds;
  373. timeout.tv_sec = 0;
  374. timeout.tv_usec = 0;
  375.     FD_ZERO (&read_fds);
  376.     FD_SET (sockNum, &read_fds);
  377. return select (sockNum+1, &read_fds, NULL, NULL, &timeout) == 1;
  378. }
  379. // --------------------------------------------------
  380. int UClientSocket::numPending() 
  381. {
  382. size_t len;
  383.     if (ioctl( sockNum, FIONREAD, (char *)&len ) < 0)
  384. throw StreamException("numPending");
  385. return (int)len;
  386. }