开源的socket服务端客户端,支持C# C++

ServerDlg.cpp 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. // ServerDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "Server.h"
  5. #include "ServerDlg.h"
  6. #include "afxdialogex.h"
  7. // CServerDlg dialog
  8. const LPCTSTR CServerDlg::ADDRESS = _T("0.0.0.0");
  9. const USHORT CServerDlg::PORT = 5555;
  10. CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/)
  11. : CDialogEx(CServerDlg::IDD, pParent), m_Server(this)
  12. {
  13. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  14. }
  15. void CServerDlg::DoDataExchange(CDataExchange* pDX)
  16. {
  17. CDialogEx::DoDataExchange(pDX);
  18. DDX_Control(pDX, IDC_INFO, m_Info);
  19. DDX_Control(pDX, IDC_START, m_Start);
  20. DDX_Control(pDX, IDC_STOP, m_Stop);
  21. DDX_Control(pDX, IDC_ADDRESS, m_Address);
  22. DDX_Control(pDX, IDC_CONN_ID, m_ConnID);
  23. DDX_Control(pDX, IDC_DISCONNECT, m_DisConn);
  24. }
  25. BEGIN_MESSAGE_MAP(CServerDlg, CDialogEx)
  26. ON_WM_PAINT()
  27. ON_WM_QUERYDRAGICON()
  28. ON_BN_CLICKED(IDC_START, &CServerDlg::OnBnClickedStart)
  29. ON_BN_CLICKED(IDC_STOP, &CServerDlg::OnBnClickedStop)
  30. ON_MESSAGE(USER_INFO_MSG, OnUserInfoMsg)
  31. ON_BN_CLICKED(IDC_DISCONNECT, &CServerDlg::OnBnClickedDisconnect)
  32. ON_EN_CHANGE(IDC_CONN_ID, &CServerDlg::OnEnChangeConnId)
  33. ON_WM_VKEYTOITEM()
  34. END_MESSAGE_MAP()
  35. // CServerDlg message handlers
  36. BOOL CServerDlg::OnInitDialog()
  37. {
  38. CDialogEx::OnInitDialog();
  39. // Set the icon for this dialog. The framework does this automatically
  40. // when the application's main window is not a dialog
  41. SetIcon(m_hIcon, TRUE); // Set big icon
  42. SetIcon(m_hIcon, FALSE); // Set small icon
  43. // TODO: Add extra initialization here
  44. CString strTitle;
  45. CString strOriginTitle;
  46. GetWindowText(strOriginTitle);
  47. strTitle.Format(_T("%s - (%s:%d)"), strOriginTitle, ADDRESS, PORT);
  48. SetWindowText(strTitle);
  49. ::SetMainWnd(this);
  50. ::SetInfoList(&m_Info);
  51. SetAppState(ST_STOPPED);
  52. return TRUE; // return TRUE unless you set the focus to a control
  53. }
  54. // If you add a minimize button to your dialog, you will need the code below
  55. // to draw the icon. For MFC applications using the document/view model,
  56. // this is automatically done for you by the framework.
  57. void CServerDlg::OnPaint()
  58. {
  59. if (IsIconic())
  60. {
  61. CPaintDC dc(this); // device context for painting
  62. SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
  63. // Center icon in client rectangle
  64. int cxIcon = GetSystemMetrics(SM_CXICON);
  65. int cyIcon = GetSystemMetrics(SM_CYICON);
  66. CRect rect;
  67. GetClientRect(&rect);
  68. int x = (rect.Width() - cxIcon + 1) / 2;
  69. int y = (rect.Height() - cyIcon + 1) / 2;
  70. // Draw the icon
  71. dc.DrawIcon(x, y, m_hIcon);
  72. }
  73. else
  74. {
  75. CDialogEx::OnPaint();
  76. }
  77. }
  78. // The system calls this function to obtain the cursor to display while the user drags
  79. // the minimized window.
  80. HCURSOR CServerDlg::OnQueryDragIcon()
  81. {
  82. return static_cast<HCURSOR>(m_hIcon);
  83. }
  84. BOOL CServerDlg::PreTranslateMessage(MSG* pMsg)
  85. {
  86. if (
  87. pMsg->message == WM_KEYDOWN
  88. &&( pMsg->wParam == VK_ESCAPE
  89. || pMsg->wParam == VK_CANCEL
  90. || pMsg->wParam == VK_RETURN
  91. ))
  92. return TRUE;
  93. return CDialog::PreTranslateMessage(pMsg);
  94. }
  95. void CServerDlg::SetAppState(EnAppState state)
  96. {
  97. m_enState = state;
  98. if(this->GetSafeHwnd() == nullptr)
  99. return;
  100. m_Start.EnableWindow(m_enState == ST_STOPPED);
  101. m_Stop.EnableWindow(m_enState == ST_STARTED);
  102. m_Address.EnableWindow(m_enState == ST_STOPPED);
  103. m_DisConn.EnableWindow(m_enState == ST_STARTED && m_ConnID.GetWindowTextLength() > 0);
  104. }
  105. void CServerDlg::OnBnClickedStart()
  106. {
  107. m_Address.GetWindowText(m_strAddress);
  108. m_strAddress.Trim();
  109. SetAppState(ST_STARTING);
  110. //m_Server->SetSocketBufferSize(64);
  111. if(m_Server->Start(ADDRESS, PORT))
  112. {
  113. ::LogServerStart(ADDRESS, PORT);
  114. SetAppState(ST_STARTED);
  115. }
  116. else
  117. {
  118. ::LogServerStartFail(m_Server->GetLastError(), m_Server->GetLastErrorDesc());
  119. SetAppState(ST_STOPPED);
  120. }
  121. }
  122. void CServerDlg::OnBnClickedStop()
  123. {
  124. SetAppState(ST_STOPPING);
  125. if(m_Server->Stop())
  126. {
  127. ::LogServerStop();
  128. SetAppState(ST_STOPPED);
  129. }
  130. else
  131. {
  132. ASSERT(FALSE);
  133. }
  134. }
  135. void CServerDlg::OnBnClickedDisconnect()
  136. {
  137. CString strConnID;
  138. m_ConnID.GetWindowText(strConnID);
  139. CONNID dwConnID = (CONNID)_ttoi(strConnID);
  140. if(m_Server->Disconnect(dwConnID))
  141. ::LogDisconnect(dwConnID);
  142. else
  143. ::LogDisconnectFail(dwConnID);
  144. }
  145. void CServerDlg::OnEnChangeConnId()
  146. {
  147. m_DisConn.EnableWindow(m_enState == ST_STARTED && m_ConnID.GetWindowTextLength() > 0);
  148. }
  149. int CServerDlg::OnVKeyToItem(UINT nKey, CListBox* pListBox, UINT nIndex)
  150. {
  151. if(nKey == 'C')
  152. pListBox->ResetContent();
  153. return __super::OnVKeyToItem(nKey, pListBox, nIndex);
  154. }
  155. LRESULT CServerDlg::OnUserInfoMsg(WPARAM wp, LPARAM lp)
  156. {
  157. info_msg* msg = (info_msg*)wp;
  158. ::LogInfoMsg(msg);
  159. return 0;
  160. }
  161. EnHandleResult CServerDlg::OnPrepareListen(ITcpServer* pSender, SOCKET soListen)
  162. {
  163. TCHAR szAddress[40];
  164. int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
  165. USHORT usPort;
  166. pSender->GetListenAddress(szAddress, iAddressLen, usPort);
  167. ::PostOnPrepareListen(szAddress, usPort);
  168. return HR_OK;
  169. }
  170. EnHandleResult CServerDlg::OnAccept(ITcpServer* pSender, CONNID dwConnID, SOCKET soClient)
  171. {
  172. BOOL bPass = TRUE;
  173. TCHAR szAddress[40];
  174. int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
  175. USHORT usPort;
  176. pSender->GetRemoteAddress(dwConnID, szAddress, iAddressLen, usPort);
  177. if(!m_strAddress.IsEmpty())
  178. {
  179. if(m_strAddress.CompareNoCase(szAddress) == 0)
  180. bPass = FALSE;
  181. }
  182. ::PostOnAccept(dwConnID, szAddress, usPort, bPass);
  183. if(bPass) pSender->SetConnectionExtra(dwConnID, new TPkgInfo(true, sizeof(TPkgHeader)));
  184. return bPass ? HR_OK : HR_ERROR;
  185. }
  186. EnHandleResult CServerDlg::OnSend(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
  187. {
  188. ::PostOnSend(dwConnID, pData, iLength);
  189. return HR_OK;
  190. }
  191. EnHandleResult CServerDlg::OnReceive(ITcpServer* pSender, CONNID dwConnID, int iLength)
  192. {
  193. TPkgInfo* pInfo = FindPkgInfo(pSender, dwConnID);
  194. ITcpPullServer* pServer = ITcpPullServer::FromS(pSender);
  195. if(pInfo != nullptr)
  196. {
  197. int required = pInfo->length;
  198. int remain = iLength;
  199. while(remain >= required)
  200. {
  201. remain -= required;
  202. CBufferPtr buffer(required);
  203. EnFetchResult result = pServer->Fetch(dwConnID, buffer, (int)buffer.Size());
  204. if(result == FR_OK)
  205. {
  206. if(pInfo->is_header)
  207. {
  208. TPkgHeader* pHeader = (TPkgHeader*)buffer.Ptr();
  209. TRACE("[Server] head -> seq: %d, body_len: %d\n", pHeader->seq, pHeader->body_len);
  210. required = pHeader->body_len;
  211. }
  212. else
  213. {
  214. TPkgBody* pBody = (TPkgBody*)(BYTE*)buffer;
  215. TRACE("[Server] body -> name: %s, age: %d, desc: %s\n", pBody->name, pBody->age, pBody->desc);
  216. required = sizeof(TPkgHeader);
  217. }
  218. pInfo->is_header = !pInfo->is_header;
  219. pInfo->length = required;
  220. ::PostOnReceive(dwConnID, buffer, (int)buffer.Size());
  221. if(!pSender->Send(dwConnID, buffer, (int)buffer.Size()))
  222. return HR_ERROR;
  223. }
  224. }
  225. }
  226. return HR_OK;
  227. }
  228. EnHandleResult CServerDlg::OnClose(ITcpServer* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
  229. {
  230. iErrorCode == SE_OK ? ::PostOnClose(dwConnID) :
  231. ::PostOnError(dwConnID, enOperation, iErrorCode);
  232. RemovePkgInfo(pSender, dwConnID);
  233. return HR_OK;
  234. }
  235. EnHandleResult CServerDlg::OnShutdown(ITcpServer* pSender)
  236. {
  237. ::PostOnShutdown();
  238. return HR_OK;
  239. }
  240. TPkgInfo* CServerDlg::FindPkgInfo(ITcpServer* pSender, CONNID dwConnID)
  241. {
  242. PVOID pInfo = nullptr;
  243. pSender->GetConnectionExtra(dwConnID, &pInfo);
  244. return (TPkgInfo*)pInfo;
  245. }
  246. void CServerDlg::RemovePkgInfo(ITcpServer* pSender, CONNID dwConnID)
  247. {
  248. TPkgInfo* pInfo = FindPkgInfo(pSender, dwConnID);
  249. ASSERT(pInfo != nullptr);
  250. delete pInfo;
  251. }