ServerLink.cpp
上传用户:hkcoast
上传日期:2007-01-12
资源大小:979k
文件大小:8k
源码类别:

手机短信编程

开发平台:

Visual C++

  1. // ServerLink.cpp: implementation of the CServerLink class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. //#include "SMPPAPI.h"
  6. #include "ServerLink.h"
  7. #include "common.h"
  8. #include "smpp.h"
  9. #include "smpppacket.h"
  10. #ifdef _DEBUG
  11. #undef THIS_FILE
  12. static char THIS_FILE[]=__FILE__;
  13. #define new DEBUG_NEW
  14. #endif
  15. //////////////////////////////////////////////////////////////////////
  16. // Construction/Destruction
  17. //////////////////////////////////////////////////////////////////////
  18. CServerLink::CServerLink() : m_bConnected(false), m_nSocket(INVALID_SOCKET),
  19. m_hEvent(WSA_INVALID_EVENT), m_bReadHeader(true)
  20. {
  21. m_nSocket = NULL;
  22. m_hEvent = NULL;
  23. m_hThread = NULL;
  24. m_pIOWinThread = NULL;
  25. //manual reset Kill event with intial signal state to false
  26. m_hKillEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  27. m_hDisconnectEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  28. //callback
  29. m_Param = NULL;
  30. m_pProcessPacket = NULL;
  31. InitializeCriticalSection(&m_cs);
  32. }
  33. CServerLink::CServerLink(CString svrip) : m_bConnected(false), m_nSocket(INVALID_SOCKET),
  34. m_hEvent(WSA_INVALID_EVENT), m_bReadHeader(true)
  35. {
  36. m_ServerIP = svrip;
  37. m_ServerPort = DEFAULT_PORT;
  38. m_nSocket = NULL;
  39. m_hEvent = NULL;
  40. m_hThread = NULL;
  41. m_pIOWinThread = NULL;
  42. //manual reset Kill event with intial signal state to false
  43. m_hKillEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  44. m_hDisconnectEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  45. //callback
  46. m_Param = NULL;
  47. m_pProcessPacket = NULL;
  48. InitializeCriticalSection(&m_cs);
  49. }
  50. CServerLink::CServerLink(CString svrip, int port) : m_bConnected(false), m_nSocket(INVALID_SOCKET),
  51. m_hEvent(WSA_INVALID_EVENT), m_bReadHeader(true)
  52. {
  53. m_ServerIP = svrip;
  54. m_ServerPort = port;
  55. m_nSocket = NULL;
  56. m_hEvent = NULL;
  57. m_hThread = NULL;
  58. m_pIOWinThread = NULL;
  59. //manual reset Kill event with intial signal state to false
  60. m_hKillEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  61. m_hDisconnectEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  62. //callback
  63. m_Param = NULL;
  64. m_pProcessPacket = NULL;
  65. InitializeCriticalSection(&m_cs);
  66. }
  67. CServerLink::~CServerLink()
  68. {
  69. SetEvent(m_hKillEvent);
  70. WaitForSingleObject(m_hThread, 500);
  71. CloseHandle(m_hKillEvent);
  72. WSACloseEvent(m_hEvent);
  73. CloseHandle(m_hDisconnectEvent);
  74. DeleteCriticalSection(&m_cs);
  75. }
  76. void CServerLink::init(CString svrip, int port)
  77. {
  78. m_ServerIP = svrip;
  79. m_ServerPort = port;
  80. }
  81. bool CServerLink::open()
  82. {
  83. EnterCriticalSection(&m_cs);
  84. bool bConnected = m_bConnected;
  85. LeaveCriticalSection(&m_cs);
  86. if (bConnected)
  87. return true;
  88. SOCKADDR_IN saServer;
  89. saServer.sin_port = htons(m_ServerPort);
  90. saServer.sin_family = AF_INET;
  91. saServer.sin_addr.s_addr = inet_addr(m_ServerIP);
  92. m_nSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  93. if (m_nSocket == INVALID_SOCKET)
  94. {
  95.         return FALSE;
  96. }
  97. int nRet = connect(m_nSocket,(sockaddr*)&saServer, sizeof(saServer));
  98. if (nRet == SOCKET_ERROR)
  99. {
  100. TCHAR buf[100];
  101. sprintf(buf, "connect error %ld",WSAGetLastError());
  102. closesocket(m_nSocket);
  103. return FALSE;
  104. }
  105. ResetEvent(m_hDisconnectEvent);
  106. m_bConnected = TRUE;
  107. TRACE("Connected to Server");
  108. //listen to event
  109. m_hEvent = WSACreateEvent();
  110. //first, we tell the system what event we are interested
  111. nRet = WSAEventSelect(m_nSocket,
  112.   m_hEvent,
  113.   FD_CLOSE | FD_READ);
  114. //create the thread to listen for events
  115. m_pIOWinThread = AfxBeginThread(IOThreadProc, //thread proc
  116. (void*) this, //parameter
  117. THREAD_PRIORITY_NORMAL, //thread priority
  118. 0, //stack size
  119. CREATE_SUSPENDED, //create thread
  120. NULL); //security attribute
  121. m_dwThreadId = m_pIOWinThread->m_nThreadID;
  122. m_hThread = m_pIOWinThread->m_hThread;
  123. m_pIOWinThread->ResumeThread();
  124. TRACE("Listen TID=%ldn",m_dwThreadId);
  125. return TRUE;
  126. }
  127. void CServerLink::close()
  128. {
  129. EnterCriticalSection(&m_cs);
  130. if (m_bConnected)
  131. {
  132. SetEvent(m_hKillEvent);
  133. WaitForSingleObject(m_hThread, 2000);
  134. closesocket(m_nSocket);
  135. SetEvent(m_hDisconnectEvent);
  136. m_bConnected = FALSE;
  137. }
  138. LeaveCriticalSection(&m_cs);
  139. }
  140. bool CServerLink::isConnected()
  141. {
  142. return m_bConnected;
  143. }
  144. CString CServerLink::getServerIP()
  145. {
  146. return m_ServerIP;
  147. }
  148. int CServerLink::getServerPort()
  149. {
  150. return m_ServerPort;
  151. }
  152. UINT CServerLink::IOThreadProc(LPVOID pParam)
  153. {
  154. return ((CServerLink *) pParam)->IOThreadRun();
  155. }
  156. unsigned CServerLink::IOThreadRun()
  157. {
  158. bool bRunning = false;
  159. bool bConnected;
  160. TRACE("Going to run the IO Threadn");
  161. while (!bRunning)
  162. {
  163. EnterCriticalSection(&m_cs);
  164. bConnected = m_bConnected;
  165. LeaveCriticalSection(&m_cs);
  166. //if it's not connected exit the IO thread
  167. if(!m_bConnected)
  168. break;
  169. //going to shutdown, exit the loop
  170.         if (WaitForSingleObject(m_hKillEvent, 0) == WAIT_OBJECT_0)
  171. {
  172. TRACE("Existing IO Thread coz of kill eventn");
  173.             break;
  174. }
  175. DWORD ret = ::WSAWaitForMultipleEvents(1, &m_hEvent, FALSE, 100, FALSE);
  176. if (ret == WSA_WAIT_EVENT_0 ) //an event is signalled
  177. {
  178. WSANETWORKEVENTS hNetworkEvent;
  179. //evaluate what's happend, read or close ?
  180. int ret1 = ::WSAEnumNetworkEvents(m_nSocket, m_hEvent, &hNetworkEvent);
  181. if (hNetworkEvent.lNetworkEvents & FD_CLOSE)
  182. {
  183. TRACE("Network event is Closen");
  184. OnClose();
  185. break;
  186. }
  187. if (hNetworkEvent.lNetworkEvents & FD_READ) //we got something to read
  188. {
  189. TRACE("Network event is Readn");
  190. OnRead();
  191. }
  192. } //wait_object_0
  193. } //while bRunning
  194. TRACE("Exiting IO Threadn");
  195. return 0; //thread exit normally
  196. }
  197. bool CServerLink::OnRead()
  198. {
  199. TRACE("OnRead - CServerLinkn");
  200. int ret;
  201. if (m_bReadHeader)
  202. {
  203. m_nTotalRead = 0;
  204. DWORD dwRead = 0;
  205. //check how many bytes we could read
  206. ioctlsocket(m_nSocket, FIONREAD, &dwRead);
  207. //can we get the preliminary header ?
  208. //we know the packet size after reading it
  209. if (dwRead < 4)
  210. return false;
  211. BYTE pkt_hdr[4];
  212. ret = recv(m_nSocket, (char *) pkt_hdr, 4,0);
  213. m_nTotalRead = 4; //CommandLen is included in the length
  214. m_nBlockSize = readInt(pkt_hdr);
  215. TCHAR buff[100];
  216. sprintf(buff, "CommandLen is : %dn", m_nBlockSize);
  217. TRACE(buff);
  218. m_bReadHeader = FALSE; //we don't have to read header later
  219. }
  220. else
  221. {
  222. //we have already read the 4-byte preliminary header
  223. DWORD dwRead = 0;
  224. //check that how many bytes we can read
  225. ioctlsocket(m_nSocket, FIONREAD, &dwRead);
  226. if (dwRead == 0)
  227. return false;
  228. //we should only read the socket up to packet size as in the header
  229. if (dwRead > (m_nBlockSize - m_nTotalRead))
  230. dwRead = m_nBlockSize - m_nTotalRead;
  231. BYTE* pBlock = new BYTE[dwRead+1];
  232. ZeroMemory(pBlock, dwRead+1);
  233. int nrec = recv(m_nSocket, (char*) pBlock, dwRead, 0);
  234. pBlock[dwRead] = NULL;
  235. m_nTotalRead+=nrec;
  236. if (m_nTotalRead == m_nBlockSize)
  237. {
  238. //we get the whole packet in pBlock
  239. parse_packet(pBlock, m_nTotalRead);
  240. //resetting
  241. m_bReadHeader = TRUE;
  242. }
  243. delete [] pBlock;
  244. }
  245. return false;
  246. }
  247. bool CServerLink::OnClose()
  248. {
  249. close();
  250. CLinkClose *ppak = new CLinkClose();
  251. //call back
  252. if (m_pProcessPacket != NULL)
  253. {
  254. m_pProcessPacket(ppak, m_Param);
  255. }
  256. delete ppak;
  257. return true;
  258. }
  259. int CServerLink::send(PBYTE data, uint32 datalen)
  260. {
  261. WSABUF sbuffer;
  262.     ULONG cb_written, retcode = 0;
  263.     int ret;
  264. if (!m_bConnected)
  265. return 0;
  266. sbuffer.len = datalen;
  267. sbuffer.buf = (char *) data;
  268. retry:
  269. //send
  270. ret = WSASend (m_nSocket, (LPWSABUF)&sbuffer, 1, &cb_written, 0, NULL, NULL);
  271. if (ret != 0) {
  272. ret = WSAGetLastError();
  273. if (ret == WSAEWOULDBLOCK) {
  274. Sleep(100);
  275. goto retry;
  276. }
  277. return ret;
  278. }
  279. if (datalen != cb_written) {
  280. // not all data send!
  281. return -1;
  282. }
  283. return 0;
  284. }
  285. bool CServerLink::sendPacket(CPacketBase &pak)
  286. {
  287. bool ret;
  288. PBYTE pby;
  289. int nsz;
  290. pak.encodeBody(pby, nsz);
  291. if( send(pby, nsz) > 0)
  292. ret = true;
  293. else
  294. ret = false;
  295. delete [] pby;
  296. return ret;
  297. }
  298. void CServerLink::registerProcessPacket(void(__stdcall *start_address)(CPacketBase *pak, LPVOID param), LPVOID param)
  299. {
  300. m_pProcessPacket = start_address;
  301. m_Param = param;
  302. }