Blocksock.cpp
上传用户:wpp2016
上传日期:2010-02-01
资源大小:1250k
文件大小:8k
源码类别:

Telnet服务器

开发平台:

Visual C++

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