SocketClientDlg.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. // SocketClientDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include <comdef.h>
  5. #include <atlbase.h>
  6. #include "SocketServer.h"
  7. #include "AboutBox.h"
  8. #include "SocketClientDlg.h"
  9. const int AF_IPV4 = 0;
  10. const int AF_IPV6 = 1;
  11. const int SOCK_TCP = SOCK_STREAM-1;
  12. const int SOCK_UDP = SOCK_DGRAM-1;
  13. // CSocketClientDlg dialog
  14. CSocketClientDlg::CSocketClientDlg(CWnd* pParent /*=NULL*/)
  15. : CDialog(CSocketClientDlg::IDD, pParent)
  16. , m_nMode(AF_IPV4)
  17. , m_nSockType(SOCK_TCP)
  18. , m_strPort(_T("2000"))
  19. {
  20. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  21. m_SocketClient.SetInterface(this);
  22. }
  23. CSocketClientDlg::~CSocketClientDlg()
  24. {
  25. }
  26. void CSocketClientDlg::DoDataExchange(CDataExchange* pDX)
  27. {
  28. CDialog::DoDataExchange(pDX);
  29. DDX_Text(pDX, IDC_SVR_PORT, m_strPort);
  30. DDX_Radio(pDX, IDC_IPV4, m_nMode);
  31. DDX_Radio(pDX, IDC_TCP, m_nSockType);
  32. DDX_Control(pDX, IDC_TXT_MESSAGE, m_ctlMessage);
  33. DDX_Control(pDX, IDC_MESSAGE_LIST, m_ctlMsgList);
  34. }
  35. BOOL CSocketClientDlg::PreTranslateMessage(MSG* pMsg)
  36. {
  37. if ( pMsg->message == WM_KEYDOWN )
  38. {
  39. if ( pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE )
  40. {
  41. if ( pMsg->wParam == VK_RETURN )
  42. {
  43. TCHAR szClassName[40] = { 0 };
  44. CWnd* pWnd = GetFocus();
  45. if ( pWnd )
  46. {
  47. GetClassName(pWnd->GetSafeHwnd(), szClassName, 40);
  48. if ( lstrcmpi(_T("EDIT"), szClassName) == 0 )
  49. {
  50. return FALSE;
  51. }
  52. }
  53. }
  54. return TRUE;
  55. }
  56. }
  57. return CDialog::PreTranslateMessage(pMsg);
  58. }
  59. BEGIN_MESSAGE_MAP(CSocketClientDlg, CDialog)
  60. ON_WM_SYSCOMMAND()
  61. ON_WM_PAINT()
  62. ON_WM_QUERYDRAGICON()
  63. //}}AFX_MSG_MAP
  64. ON_WM_DESTROY()
  65. ON_COMMAND_RANGE(IDC_IPV4, IDC_IPV6, OnModeSelected)
  66. ON_BN_CLICKED(IDC_BTN_START, &CSocketClientDlg::OnBnClickedBtnStart)
  67. ON_BN_CLICKED(IDC_BTN_STOP, &CSocketClientDlg::OnBnClickedBtnStop)
  68. ON_BN_CLICKED(IDC_BTN_SEND, &CSocketClientDlg::OnBnClickedBtnSend)
  69. END_MESSAGE_MAP()
  70. // CSocketClientDlg message handlers
  71. BOOL CSocketClientDlg::OnInitDialog()
  72. {
  73. CDialog::OnInitDialog();
  74. // Add "About..." menu item to system menu.
  75. // IDM_ABOUTBOX must be in the system command range.
  76. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  77. ASSERT(IDM_ABOUTBOX < 0xF000);
  78. CMenu* pSysMenu = GetSystemMenu(FALSE);
  79. if (pSysMenu != NULL)
  80. {
  81. CString strAboutMenu;
  82. strAboutMenu.LoadString(IDS_ABOUTBOX);
  83. if (!strAboutMenu.IsEmpty())
  84. {
  85. pSysMenu->AppendMenu(MF_SEPARATOR);
  86. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  87. }
  88. }
  89. // Set the icon for this dialog. The framework does this automatically
  90. // when the application's main window is not a dialog
  91. SetIcon(m_hIcon, TRUE); // Set big icon
  92. SetIcon(m_hIcon, FALSE); // Set small icon
  93. // TODO: Add extra initialization here
  94. TCHAR szLocalAddr[MAX_PATH] = { 0 };
  95. int nFamily = (m_nMode == AF_IPV4) ? AF_INET : AF_INET6;
  96. CSocketHandle::GetLocalAddress(szLocalAddr, MAX_PATH, nFamily);
  97. SetDlgItemText(IDC_IPADDRESS, szLocalAddr);
  98. SendDlgItemMessage(IDC_SVR_PORTINC, UDM_SETRANGE32, 2000, 64000);
  99. m_ctlMsgList.SetLimitText( 1*1024*1024 );
  100. m_ctlMessage.SetFocus();
  101. SyncControls();
  102. return TRUE; // return TRUE unless you set the focus to a control
  103. }
  104. void CSocketClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
  105. {
  106. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  107. {
  108. CAboutDlg dlgAbout;
  109. dlgAbout.DoModal();
  110. }
  111. else
  112. {
  113. CDialog::OnSysCommand(nID, lParam);
  114. }
  115. }
  116. // If you add a minimize button to your dialog, you will need the code below
  117. // to draw the icon. For MFC applications using the document/view model,
  118. // this is automatically done for you by the framework.
  119. void CSocketClientDlg::OnPaint()
  120. {
  121. if (IsIconic())
  122. {
  123. CPaintDC dc(this); // device context for painting
  124. SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
  125. // Center icon in client rectangle
  126. int cxIcon = GetSystemMetrics(SM_CXICON);
  127. int cyIcon = GetSystemMetrics(SM_CYICON);
  128. CRect rect;
  129. GetClientRect(&rect);
  130. int x = (rect.Width() - cxIcon + 1) / 2;
  131. int y = (rect.Height() - cyIcon + 1) / 2;
  132. // Draw the icon
  133. dc.DrawIcon(x, y, m_hIcon);
  134. }
  135. else
  136. {
  137. CDialog::OnPaint();
  138. }
  139. }
  140. // The system calls this function to obtain the cursor to display while the user drags
  141. // the minimized window.
  142. HCURSOR CSocketClientDlg::OnQueryDragIcon()
  143. {
  144. return static_cast<HCURSOR>(m_hIcon);
  145. }
  146. void CSocketClientDlg::OnDestroy()
  147. {
  148. m_SocketClient.Terminate();
  149. CDialog::OnDestroy();
  150. }
  151. void CSocketClientDlg::EnableControl(UINT nCtrlID, BOOL bEnable)
  152. {
  153. GetDlgItem(nCtrlID)->EnableWindow(bEnable);
  154. }
  155. void CSocketClientDlg::SyncControls()
  156. {
  157. bool bOpen = m_SocketClient.IsOpen();
  158. EnableControl(IDC_BTN_START, !bOpen);
  159. EnableControl(IDC_BTN_STOP, bOpen);
  160. EnableControl(IDC_BTN_SEND, bOpen);
  161. EnableControl(IDC_IPV4, !bOpen);
  162. EnableControl(IDC_IPV6, !bOpen);
  163. EnableControl(IDC_TCP, !bOpen);
  164. EnableControl(IDC_UDP, !bOpen);
  165. }
  166. void CSocketClientDlg::GetAddress(const SockAddrIn& addrIn, CString& rString) const
  167. {
  168. TCHAR szIPAddr[MAX_PATH] = { 0 };
  169. CSocketHandle::FormatIP(szIPAddr, MAX_PATH, addrIn);
  170. rString.Format(_T("%s : %d"), szIPAddr, static_cast<int>(static_cast<UINT>(ntohs(addrIn.GetPort()))) );
  171. }
  172. void CSocketClientDlg::AppendText(LPCTSTR lpszFormat, ...)
  173. {
  174. if ( !::IsWindow(m_ctlMsgList.GetSafeHwnd()) ) return;
  175. TCHAR szBuffer[512];
  176. HWND hWnd = m_ctlMsgList.GetSafeHwnd();
  177. DWORD dwResult = 0;
  178. if (SendMessageTimeout(hWnd, WM_GETTEXTLENGTH, 0, 0, SMTO_NORMAL, 500L, &dwResult) != 0)
  179. {
  180. int nLen = (int) dwResult;
  181. if (SendMessageTimeout(hWnd, EM_SETSEL, nLen, nLen, SMTO_NORMAL, 500L, &dwResult) != 0)
  182. {
  183. size_t cb = 0;
  184. va_list args;
  185. va_start(args, lpszFormat);
  186. ::StringCchVPrintfEx(szBuffer, 512, NULL, &cb, 0, lpszFormat, args);
  187. va_end(args);
  188. SendMessageTimeout(hWnd, EM_REPLACESEL, FALSE, reinterpret_cast<LPARAM>(szBuffer), SMTO_NORMAL, 500L, &dwResult);
  189. }
  190. }
  191. }
  192. bool CSocketClientDlg::GetDestination(SockAddrIn& addrIn) const
  193. {
  194. CString strIPAddress, strPort;
  195. GetDlgItemText(IDC_IPADDRESS, strIPAddress);
  196. GetDlgItemText(IDC_SVR_PORT, strPort);
  197. int nFamily = (m_nMode == AF_IPV4) ? AF_INET : AF_INET6;
  198. return addrIn.CreateFrom(strIPAddress, strPort, nFamily);
  199. }
  200. bool CSocketClientDlg::SetupMCAST()
  201. {
  202. const TCHAR szIPv4MCAST[] = TEXT("239.121.1.2");
  203. const TCHAR szIPv6MCAST[] = TEXT("FF02:0:0:0:0:0:0:1"); // All Nodes local address
  204. bool result = false;
  205. if ( m_nSockType == SOCK_UDP )
  206. {
  207. if ( m_nMode == AF_IPV4 ) {
  208. result = m_SocketClient->AddMembership(szIPv4MCAST, NULL);
  209. } else {
  210. result = m_SocketClient->AddMembership(szIPv6MCAST, NULL);
  211. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  212. hr = hr;
  213. }
  214. }
  215. return result;
  216. }
  217. ///////////////////////////////////////////////////////////////////////////////
  218. void CSocketClientDlg::OnThreadBegin(CSocketHandle* pSH)
  219. {
  220. ASSERT( pSH == m_SocketClient );
  221. (pSH);
  222. CString strAddr;
  223. SockAddrIn sockAddr;
  224. m_SocketClient->GetSockName(sockAddr);
  225. GetAddress( sockAddr, strAddr );
  226. AppendText( _T("Client Running on: %s\r\n"), strAddr);
  227. }
  228. void CSocketClientDlg::OnThreadExit(CSocketHandle* pSH)
  229. {
  230. ASSERT( pSH == m_SocketClient );
  231. (pSH);
  232. }
  233. void CSocketClientDlg::OnDataReceived(CSocketHandle* pSH, const BYTE* pbData, DWORD dwCount, const SockAddrIn& addr)
  234. {
  235. ASSERT( pSH == m_SocketClient );
  236. (pSH);
  237. CString strAddr, strText;
  238. USES_CONVERSION;
  239. LPTSTR pszText = strText.GetBuffer(dwCount+1);
  240. ::StringCchCopyN(pszText, dwCount+1, A2CT(reinterpret_cast<LPCSTR>(pbData)), dwCount);
  241. strText.ReleaseBuffer();
  242. GetAddress( addr, strAddr );
  243. AppendText( _T("%s>(%s)\r\n"), strAddr, strText);
  244. }
  245. void CSocketClientDlg::OnConnectionDropped(CSocketHandle* pSH)
  246. {
  247. ASSERT( pSH == m_SocketClient );
  248. (pSH);
  249. AppendText( _T("Connection lost with server. Need restart.\r\n") );
  250. }
  251. void CSocketClientDlg::OnConnectionError(CSocketHandle* pSH, DWORD dwError)
  252. {
  253. ASSERT( pSH == m_SocketClient );
  254. (pSH);
  255. _com_error err(dwError);
  256. AppendText( _T("Communication Error:\r\n%s\r\n"), err.ErrorMessage() );
  257. }
  258. void CSocketClientDlg::OnModeSelected(UINT nId)
  259. {
  260. m_nMode = nId - IDC_IPV4;
  261. TCHAR szLocalAddr[MAX_PATH] = { 0 };
  262. int nFamily = (m_nMode == AF_IPV4) ? AF_INET : AF_INET6;
  263. CSocketHandle::GetLocalAddress(szLocalAddr, MAX_PATH, nFamily);
  264. SetDlgItemText(IDC_IPADDRESS, szLocalAddr);
  265. }
  266. void CSocketClientDlg::OnBnClickedBtnStart()
  267. {
  268. UpdateData(TRUE);
  269. CString strAddr, strPort;
  270. GetDlgItemText(IDC_IPADDRESS, strAddr);
  271. GetDlgItemText(IDC_SVR_PORT, strPort);
  272. int nFamily = (m_nMode == AF_IPV4) ? AF_INET : AF_INET6;
  273. if ( !m_SocketClient.StartClient(NULL, strAddr, strPort, nFamily, (m_nSockType+1) ) )
  274. {
  275. MessageBox(_T("Failed to start client connection."), NULL, MB_ICONSTOP);
  276. }
  277. else
  278. {
  279. SetupMCAST();
  280. }
  281. SyncControls();
  282. }
  283. void CSocketClientDlg::OnBnClickedBtnStop()
  284. {
  285. m_SocketClient.Terminate();
  286. SyncControls();
  287. }
  288. void CSocketClientDlg::OnBnClickedBtnSend()
  289. {
  290. if ( m_SocketClient.IsOpen() )
  291. {
  292. CString strMsg;
  293. m_ctlMessage.GetWindowText( strMsg );
  294. if ( strMsg.IsEmpty() ) {
  295. AppendText( _T("Please enter the message to send.\r\n") );
  296. return;
  297. }
  298. USES_CONVERSION;
  299. if (m_nSockType == SOCK_TCP)
  300. {
  301. m_SocketClient.Write((const LPBYTE)(T2CA(strMsg)), strMsg.GetLength(), NULL);
  302. }
  303. else
  304. {
  305. SockAddrIn sockAddr;
  306. GetDestination(sockAddr);
  307. m_SocketClient.Write((const LPBYTE)(T2CA(strMsg)), strMsg.GetLength(), sockAddr);
  308. }
  309. }
  310. else
  311. {
  312. MessageBox(_T("Socket is not connected"));
  313. }
  314. }