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

Telnet服务器

开发平台:

Visual C++

  1. // blocksock.cpp (CBlockingSocketException, CBlockingSocket, CHttpBlockingSocket)
  2. #include <stdafx.h>
  3. #include "blocksock.h"
  4. // Class CBlockingSocketException
  5. IMPLEMENT_DYNAMIC(CBlockingSocketException, CException)
  6. CBlockingSocketException::CBlockingSocketException(char* pchMessage)
  7. {
  8. m_strMessage = pchMessage;
  9. m_nError = WSAGetLastError();
  10. }
  11. BOOL CBlockingSocketException::GetErrorMessage(LPTSTR lpstrError, UINT nMaxError,
  12. PUINT pnHelpContext /*= NULL*/)
  13. {
  14. char text[200];
  15. if(m_nError == 0) {
  16. wsprintf(text, "%s error", (const char*) m_strMessage);
  17. }
  18. else {
  19. wsprintf(text, "%s error #%d", (const char*) m_strMessage, m_nError);
  20. }
  21. strncpy(lpstrError, text, nMaxError - 1);
  22. return TRUE;
  23. }
  24. // Class CBlockingSocket
  25. IMPLEMENT_DYNAMIC(CBlockingSocket, CObject)
  26. void CBlockingSocket::Cleanup()
  27. {
  28. // doesn't throw an exception because it's called in a catch block
  29. if(m_hSocket == NULL) return;
  30. VERIFY(closesocket(m_hSocket) != SOCKET_ERROR);
  31. m_hSocket = NULL;
  32. }
  33. void CBlockingSocket::Create(int nType /* = SOCK_STREAM */)
  34. {
  35. ASSERT(m_hSocket == NULL);
  36. if((m_hSocket = socket(AF_INET, nType, 0)) == INVALID_SOCKET) {
  37. throw new CBlockingSocketException("Create");
  38. }
  39. }
  40. void CBlockingSocket::Bind(LPCSOCKADDR psa)
  41. {
  42. ASSERT(m_hSocket != NULL);
  43. if(bind(m_hSocket, psa, sizeof(SOCKADDR)) == SOCKET_ERROR) {
  44. throw new CBlockingSocketException("Bind");
  45. }
  46. }
  47. void CBlockingSocket::Listen()
  48. {
  49. ASSERT(m_hSocket != NULL);
  50. if(listen(m_hSocket, 5) == SOCKET_ERROR) {
  51. throw new CBlockingSocketException("Listen");
  52. }
  53. }
  54. BOOL CBlockingSocket::Accept(CBlockingSocket& sConnect, LPSOCKADDR psa)
  55. {
  56. ASSERT(m_hSocket != NULL);
  57. ASSERT(sConnect.m_hSocket == NULL);
  58. int nLengthAddr = sizeof(SOCKADDR);
  59. sConnect.m_hSocket = accept(m_hSocket, psa, &nLengthAddr);
  60. if(sConnect == INVALID_SOCKET) {
  61. // no exception if the listen was canceled
  62. if(WSAGetLastError() != WSAEINTR) {
  63. throw new CBlockingSocketException("Accept");
  64. }
  65. return FALSE;
  66. }
  67. return TRUE;
  68. }
  69. void CBlockingSocket::Close()
  70. {
  71. ASSERT(m_hSocket != NULL);
  72. if(closesocket(m_hSocket) == SOCKET_ERROR) {
  73. // should be OK to close if closed already
  74. throw new CBlockingSocketException("Close");
  75. }
  76. m_hSocket = NULL;
  77. }
  78. void CBlockingSocket::Connect(LPCSOCKADDR psa)
  79. {
  80. ASSERT(m_hSocket != NULL);
  81. // should timeout by itself
  82. if(connect(m_hSocket, psa, sizeof(SOCKADDR)) == SOCKET_ERROR) {
  83. throw new CBlockingSocketException("Connect");
  84. }
  85. }
  86. int CBlockingSocket::Write(const char* pch, const int nSize, const int nSecs)
  87. {
  88. int nBytesSent = 0;
  89. int nBytesThisTime;
  90. const char* pch1 = pch;
  91. do {
  92. nBytesThisTime = Send(pch1, nSize - nBytesSent, nSecs);
  93. nBytesSent += nBytesThisTime;
  94. pch1 += nBytesThisTime;
  95. } while(nBytesSent < nSize);
  96. return nBytesSent;
  97. }
  98. int CBlockingSocket::Send(const char* pch, const int nSize, const int nSecs)
  99. {
  100. ASSERT(m_hSocket != NULL);
  101. // returned value will be less than nSize if client cancels the reading
  102. FD_SET fd = {1, m_hSocket};
  103. TIMEVAL tv = {nSecs, 0};
  104. if(select(0, NULL, &fd, NULL, &tv) == 0) {
  105. throw new CBlockingSocketException("Send timeout");
  106. }
  107. int nBytesSent;
  108. if((nBytesSent = send(m_hSocket, pch, nSize, 0)) == SOCKET_ERROR) {
  109. throw new CBlockingSocketException("Send");
  110. }
  111. return nBytesSent;
  112. }
  113. int CBlockingSocket::Receive(char* pch, const int nSize, 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 new CBlockingSocketException("Receive timeout");
  120. }
  121. int nBytesReceived;
  122. if((nBytesReceived = recv(m_hSocket, pch, nSize, 0)) == SOCKET_ERROR) {
  123. throw new CBlockingSocketException("Receive");
  124. }
  125. return nBytesReceived;
  126. }
  127. int CBlockingSocket::ReceiveDatagram(char* pch, const int nSize, LPSOCKADDR psa, const int nSecs)
  128. {
  129. ASSERT(m_hSocket != NULL);
  130. FD_SET fd = {1, m_hSocket};
  131. TIMEVAL tv = {nSecs, 0};
  132. if(select(0, &fd, NULL, NULL, &tv) == 0) {
  133. throw new CBlockingSocketException("Receive timeout");
  134. }
  135. // input buffer should be big enough for the entire datagram
  136. int nFromSize = sizeof(SOCKADDR);
  137. int nBytesReceived = recvfrom(m_hSocket, pch, nSize, 0, psa, &nFromSize);
  138. if(nBytesReceived == SOCKET_ERROR) {
  139. throw new CBlockingSocketException("ReceiveDatagram");
  140. }
  141. return nBytesReceived;
  142. }
  143. int CBlockingSocket::SendDatagram(const char* pch, const int nSize, LPCSOCKADDR psa, const int nSecs)
  144. {
  145. ASSERT(m_hSocket != NULL);
  146. FD_SET fd = {1, m_hSocket};
  147. TIMEVAL tv = {nSecs, 0};
  148. if(select(0, NULL, &fd, NULL, &tv) == 0) {
  149. throw new CBlockingSocketException("Send timeout");
  150. }
  151. int nBytesSent = sendto(m_hSocket, pch, nSize, 0, psa, sizeof(SOCKADDR));
  152. if(nBytesSent == SOCKET_ERROR) {
  153. throw new CBlockingSocketException("SendDatagram");
  154. }
  155. return nBytesSent;
  156. }
  157. void CBlockingSocket::GetPeerAddr(LPSOCKADDR psa)
  158. {
  159. ASSERT(m_hSocket != NULL);
  160. // gets the address of the socket at the other end
  161. int nLengthAddr = sizeof(SOCKADDR);
  162. if(getpeername(m_hSocket, psa, &nLengthAddr) == SOCKET_ERROR) {
  163. throw new CBlockingSocketException("GetPeerName");
  164. }
  165. }
  166. void CBlockingSocket::GetSockAddr(LPSOCKADDR psa)
  167. {
  168. ASSERT(m_hSocket != NULL);
  169. // gets the address of the socket at this end
  170. int nLengthAddr = sizeof(SOCKADDR);
  171. if(getsockname(m_hSocket, psa, &nLengthAddr) == SOCKET_ERROR) {
  172. throw new CBlockingSocketException("GetSockName");
  173. }
  174. }
  175. //static
  176. CSockAddr CBlockingSocket::GetHostByName(const char* pchName, const USHORT ushPort /* = 0 */)
  177. {
  178. hostent* pHostEnt = gethostbyname(pchName);
  179. if(pHostEnt == NULL) {
  180. throw new CBlockingSocketException("GetHostByName");
  181. }
  182. ULONG* pulAddr = (ULONG*) pHostEnt->h_addr_list[0];
  183. SOCKADDR_IN sockTemp;
  184. sockTemp.sin_family = AF_INET;
  185. sockTemp.sin_port = htons(ushPort);
  186. sockTemp.sin_addr.s_addr = *pulAddr; // address is already in network byte order
  187. return sockTemp;
  188. }
  189. //static
  190. const char* CBlockingSocket::GetHostByAddr(LPCSOCKADDR psa)
  191. {
  192. hostent* pHostEnt = gethostbyaddr((char*) &((LPSOCKADDR_IN) psa)
  193. ->sin_addr.s_addr, 4, PF_INET);
  194. if(pHostEnt == NULL) {
  195. throw new CBlockingSocketException("GetHostByAddr");
  196. }
  197. return pHostEnt->h_name; // caller shouldn't delete this memory
  198. }