blockingsocket.cpp
上传用户:loctite114
上传日期:2007-01-03
资源大小:49k
文件大小:8k
源码类别:

棋牌游戏

开发平台:

Visual C++

  1. // Copyright (c) 1999 Lee Patterson
  2. // leepatterson@home.com
  3. // blocksock.cpp (CBlockingSocketException, CBlockingSocket, CHttpBlockingSocket)
  4. #include <winsock.h>
  5. #include <assert.h>
  6. #include <stdio.h>
  7. #include "blockingsocket.h"
  8. #define ASSERT assert
  9. #define VERIFY ASSERT
  10. // Class CBlockingSocket
  11. void CBlockingSocket::Cleanup()
  12. {
  13. // doesn't throw an exception because it's called in a catch block
  14. if(m_hSocket == NULL) return;
  15. closesocket(m_hSocket);
  16. m_hSocket = NULL;
  17. }
  18. void CBlockingSocket::Create(int nType /* = SOCK_STREAM */)
  19. {
  20. ASSERT(m_hSocket == NULL);
  21. if((m_hSocket = socket(AF_INET, nType, 0)) == INVALID_SOCKET) {
  22. throw "Create";
  23. }
  24. }
  25. void CBlockingSocket::Bind(LPCSOCKADDR psa)
  26. {
  27. ASSERT(m_hSocket != NULL);
  28. if(bind(m_hSocket, psa, sizeof(SOCKADDR)) == SOCKET_ERROR) {
  29. throw "Bind";
  30. }
  31. }
  32. void CBlockingSocket::Listen()
  33. {
  34. ASSERT(m_hSocket != NULL);
  35. if(listen(m_hSocket, 5) == SOCKET_ERROR) {
  36. //throw "Listen";
  37. throw "Listen";
  38. }
  39. }
  40. bool CBlockingSocket::Accept(CBlockingSocket& sConnect, LPSOCKADDR psa)
  41. {
  42. ASSERT(m_hSocket != NULL);
  43. ASSERT(sConnect.m_hSocket == NULL);
  44. int nLengthAddr = sizeof(SOCKADDR);
  45. sConnect.m_hSocket = accept(m_hSocket, psa, &nLengthAddr);
  46. if(sConnect == INVALID_SOCKET) {
  47. // no exception if the listen was canceled
  48. if(WSAGetLastError() != WSAEINTR) {
  49. throw "Accept";
  50. }
  51. return FALSE;
  52. }
  53. return TRUE;
  54. }
  55. void CBlockingSocket::Close()
  56. {
  57. ASSERT(m_hSocket != NULL);
  58. if(closesocket(m_hSocket) == SOCKET_ERROR) {
  59. // should be OK to close if closed already
  60. throw "Close";
  61. }
  62. m_hSocket = NULL;
  63. }
  64. void CBlockingSocket::Connect(LPCSOCKADDR psa)
  65. {
  66. ASSERT(m_hSocket != NULL);
  67. // should timeout by itself
  68. if(connect(m_hSocket, psa, sizeof(SOCKADDR)) == SOCKET_ERROR) {
  69. throw "Connect";
  70. }
  71. }
  72. int CBlockingSocket::Write(const char* pch, const int nSize, const int nSecs)
  73. {
  74. int nBytesSent = 0;
  75. int nBytesThisTime;
  76. const char* pch1 = pch;
  77. do {
  78. nBytesThisTime = Send(pch1, nSize - nBytesSent, nSecs);
  79. nBytesSent += nBytesThisTime;
  80. pch1 += nBytesThisTime;
  81. } while(nBytesSent < nSize);
  82. return nBytesSent;
  83. }
  84. int CBlockingSocket::Send(const char* pch, const int nSize, const int nSecs)
  85. {
  86. ASSERT(m_hSocket != NULL);
  87. // returned value will be less than nSize if client cancels the reading
  88. FD_SET fd = {1, m_hSocket};
  89. TIMEVAL tv = {nSecs, 0};
  90. if(select(0, NULL, &fd, NULL, &tv) == 0) {
  91. throw "Send timeout";
  92. }
  93. int nBytesSent;
  94. if((nBytesSent = send(m_hSocket, pch, nSize, 0)) == SOCKET_ERROR) {
  95. throw "Send";
  96. }
  97. return nBytesSent;
  98. }
  99. int CBlockingSocket::Receive(char* pch, const int nSize, const int nSecs)
  100. {
  101. ASSERT(m_hSocket != NULL);
  102. FD_SET fd = {1, m_hSocket};
  103. TIMEVAL tv = {nSecs, 0};
  104. if(select(0, &fd, NULL, NULL, &tv) == 0) {
  105. throw "Receive timeout";
  106. }
  107. int nBytesReceived;
  108. if((nBytesReceived = recv(m_hSocket, pch, nSize, 0)) == SOCKET_ERROR) {
  109. throw "Receive";
  110. }
  111. return nBytesReceived;
  112. }
  113. int CBlockingSocket::ReceiveDatagram(char* pch, const int nSize, LPSOCKADDR psa, const int nSecs)
  114. {
  115. ASSERT(m_hSocket != NULL);
  116. FD_SET fd = {1, m_hSocket};
  117. TIMEVAL tv = {nSecs, 0};
  118. if(select(0, &fd, NULL, NULL, &tv) == 0) {
  119. throw "Receive timeout";
  120. }
  121. // input buffer should be big enough for the entire datagram
  122. int nFromSize = sizeof(SOCKADDR);
  123. int nBytesReceived = recvfrom(m_hSocket, pch, nSize, 0, psa, &nFromSize);
  124. if(nBytesReceived == SOCKET_ERROR) {
  125. throw "ReceiveDatagram";
  126. }
  127. return nBytesReceived;
  128. }
  129. int CBlockingSocket::SendDatagram(const char* pch, const int nSize, LPCSOCKADDR psa, const int nSecs)
  130. {
  131. ASSERT(m_hSocket != NULL);
  132. FD_SET fd = {1, m_hSocket};
  133. TIMEVAL tv = {nSecs, 0};
  134. if(select(0, NULL, &fd, NULL, &tv) == 0) {
  135. throw "Send timeout";
  136. }
  137. int nBytesSent = sendto(m_hSocket, pch, nSize, 0, psa, sizeof(SOCKADDR));
  138. if(nBytesSent == SOCKET_ERROR) {
  139. throw "SendDatagram";
  140. }
  141. return nBytesSent;
  142. }
  143. void CBlockingSocket::GetPeerAddr(LPSOCKADDR psa)
  144. {
  145. ASSERT(m_hSocket != NULL);
  146. // gets the address of the socket at the other end
  147. int nLengthAddr = sizeof(SOCKADDR);
  148. if(getpeername(m_hSocket, psa, &nLengthAddr) == SOCKET_ERROR) {
  149. throw "GetPeerName";
  150. }
  151. }
  152. void CBlockingSocket::GetSockAddr(LPSOCKADDR psa)
  153. {
  154. ASSERT(m_hSocket != NULL);
  155. // gets the address of the socket at this end
  156. int nLengthAddr = sizeof(SOCKADDR);
  157. if(getsockname(m_hSocket, psa, &nLengthAddr) == SOCKET_ERROR) {
  158. throw "GetSockName";
  159. }
  160. }
  161. //static
  162. CSockAddr CBlockingSocket::GetHostByName(const char* pchName, const USHORT ushPort /* = 0 */)
  163. {
  164. hostent* pHostEnt = gethostbyname(pchName);
  165. if(pHostEnt == NULL) {
  166. throw "GetHostByName";
  167. }
  168. ULONG* pulAddr = (ULONG*) pHostEnt->h_addr_list[0];
  169. SOCKADDR_IN sockTemp;
  170. sockTemp.sin_family = AF_INET;
  171. sockTemp.sin_port = htons(ushPort);
  172. sockTemp.sin_addr.s_addr = *pulAddr; // address is already in network byte order
  173. return sockTemp;
  174. }
  175. //static
  176. const char* CBlockingSocket::GetHostByAddr(LPCSOCKADDR psa)
  177. {
  178. hostent* pHostEnt = gethostbyaddr((char*) &((LPSOCKADDR_IN) psa)
  179. ->sin_addr.s_addr, 4, PF_INET);
  180. if(pHostEnt == NULL) {
  181. throw "GetHostByAddr";
  182. }
  183. return pHostEnt->h_name; // caller shouldn't delete this memory
  184. }
  185. CTelnetSocket::CTelnetSocket()
  186. {
  187. m_pReadBuf   = new char[nSizeRecv];
  188. m_nReadBuf   = 0;
  189. m_wFlags     = 0;
  190. m_pLoginName = NULL;
  191. }
  192. CTelnetSocket::~CTelnetSocket()
  193. {
  194. delete [] m_pReadBuf;
  195. if(m_pLoginName) delete [] m_pLoginName;
  196. }
  197. bool CTelnetSocket::SetLoginName(const char* pname)
  198. {
  199. m_pLoginName=(char*)malloc(strlen(pname)+1);
  200. if(!m_pLoginName)
  201. return false;
  202. strcpy(m_pLoginName,pname);
  203. m_pLoginName[strlen(pname)]='';
  204. return true;
  205. }
  206. int CTelnetSocket::ReadLine(char* pch, const int nSize, const int nSecs)
  207. // reads an entire header line through CRLF (or socket close)
  208. // inserts zero string terminator, object maintains a buffer
  209. {
  210. int nBytesThisTime = m_nReadBuf;
  211. int nLineLength = 0;
  212. char* pch1 = m_pReadBuf;
  213. char* pch2;
  214. do {
  215. // look for lf (assume preceded by cr)
  216. if((pch2 = (char*) memchr(pch1 , 'n', nBytesThisTime)) != NULL) {
  217. ASSERT((pch2) > m_pReadBuf);
  218. ASSERT(*(pch2 - 1) == 'r');
  219. nLineLength = (pch2 - m_pReadBuf) + 1;
  220. if(nLineLength >= nSize) nLineLength = nSize - 1;
  221. memcpy(pch, m_pReadBuf, nLineLength); // copy the line to caller
  222. m_nReadBuf -= nLineLength;
  223. memmove(m_pReadBuf, pch2 + 1, m_nReadBuf); // shift remaining characters left
  224. break;
  225. }
  226. pch1 += nBytesThisTime;
  227. nBytesThisTime = Receive(m_pReadBuf + m_nReadBuf, nSizeRecv - m_nReadBuf, nSecs);
  228. if(nBytesThisTime <= 0) { // sender closed socket or line longer than buffer
  229. throw "ReadHeaderLine";
  230. }
  231. //update telnet session
  232. try 
  233. {
  234. Write(m_pReadBuf + m_nReadBuf,nBytesThisTime);
  235. }
  236. catch(const char* e) 
  237. {
  238. e=e;
  239. throw "ReadHeaderLine::write";
  240. }
  241. m_nReadBuf += nBytesThisTime;
  242. }
  243. while(TRUE);
  244. *(pch + nLineLength-2) = ''; //add rest of buffer, and remove lfcr
  245. return nLineLength;
  246. }
  247. int CTelnetSocket::ReadResponse(char* pch, const int nSize, const int nSecs)
  248. // reads remainder of a transmission through buffer full or socket close
  249. // (assume headers have been read already)
  250. {
  251. int nBytesToRead, nBytesThisTime, nBytesRead = 0;
  252. if(m_nReadBuf > 0) { // copy anything already in the recv buffer
  253. memcpy(pch, m_pReadBuf, m_nReadBuf);
  254. pch += m_nReadBuf;
  255. nBytesRead = m_nReadBuf;
  256. m_nReadBuf = 0;
  257. }
  258. do { // now pass the rest of the data directly to the caller
  259. nBytesToRead = min(nSizeRecv, nSize - nBytesRead);
  260. nBytesThisTime = Receive(pch, nBytesToRead, nSecs);
  261. if(nBytesThisTime <= 0) break; // sender closed the socket
  262. pch += nBytesThisTime;
  263. nBytesRead += nBytesThisTime;
  264. }
  265. while(nBytesRead <= nSize);
  266. return nBytesRead;
  267. }
  268. int CTelnetSocket::Print(const char* msg)
  269. {
  270. int iBytes;
  271. char* buf=(char*)malloc(strlen(msg)+3);
  272. sprintf(buf,"%srn",msg);
  273. iBytes=Write(buf,strlen(buf));
  274. free(buf);
  275. return iBytes;
  276. }