1 ///////////////////////////////////////
\r
5 #include "SvrDialog.h"
\r
6 #include "DialogApp.h"
\r
7 #include "resource.h"
\r
10 /////////////////////////////////////////////
\r
11 // Definitions for the CTCPClientDlg class
\r
12 CTCPClientDlg::CTCPClientDlg(UINT nResID, CWnd* pParent) :
\r
13 CDialog(nResID, pParent), m_pSocket(0)
\r
17 void CTCPClientDlg::Append(int nID, LPCTSTR buf)
\r
19 // This function appends some text to an edit control
\r
22 int ndx = (int)SendDlgItemMessage(nID, WM_GETTEXTLENGTH, 0, 0);
\r
26 SendDlgItemMessage(nID, EM_SETSEL, (WPARAM)ndx, (LPARAM)ndx);
\r
27 SendDlgItemMessage(nID, EM_REPLACESEL, 0, (LPARAM) (_T( "\r\n")));
\r
31 ndx = (int)SendDlgItemMessage(nID, WM_GETTEXTLENGTH, 0, 0);
\r
32 SendDlgItemMessage(nID, EM_SETSEL, (WPARAM)ndx, (LPARAM)ndx);
\r
33 SendDlgItemMessage(nID, EM_REPLACESEL, 0, (LPARAM) buf);
\r
36 INT_PTR CTCPClientDlg::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
41 // Disconnect the socket when the user closes this chat dialog
\r
42 m_pSocket->Disconnect();
\r
46 // Pass unhandled messages on to parent DialogProc
\r
47 return DialogProcDefault(uMsg, wParam, lParam);
\r
50 BOOL CTCPClientDlg::OnCommand(WPARAM wParam, LPARAM lParam)
\r
52 // Respond to the various dialog buttons
\r
54 UNREFERENCED_PARAMETER(lParam);
\r
56 switch (LOWORD(wParam))
\r
58 case IDC_BUTTON_SEND2:
\r
66 BOOL CTCPClientDlg::OnInitDialog()
\r
68 SetForegroundWindow();
\r
70 m_EditSend.AttachDlgItem(IDC_EDIT_SEND2, this);
\r
71 m_EditReceive.AttachDlgItem(IDC_EDIT_RECEIVE2, this);
\r
72 m_ButtonSend.AttachDlgItem(IDC_BUTTON_SEND2, this);
\r
77 void CTCPClientDlg::Receive()
\r
79 std::vector<TCHAR> vTChar( 1025, _T('\0') );
\r
80 TCHAR* buf = &vTChar.front(); // TChar array with 1025 elements initialised to _T('\0')
\r
81 m_pSocket->Receive(buf, 1024, 0);
\r
82 Append(IDC_EDIT_RECEIVE2, buf);
\r
85 void CTCPClientDlg::Send()
\r
87 CString sSend = m_EditSend.GetWindowText();
\r
88 m_pSocket->Send(sSend, lstrlen(sSend), 0);
\r
93 /////////////////////////////////////////////
\r
94 // Definitions for the CSvrDialog class
\r
95 CSvrDialog::CSvrDialog(UINT nResID, CWnd* pParent) : CDialog(nResID, pParent),
\r
96 m_bServerStarted(FALSE), m_SocketType(SOCK_STREAM)
\r
98 // Add support for the IP Address control
\r
99 // It requires Win95 with IE4 intergrated or a later version of Windows OS.
\r
100 LoadCommonControlsEx();
\r
103 CSvrDialog::~CSvrDialog()
\r
108 void CSvrDialog::Append(int nID, LPCTSTR buf)
\r
110 // This function appends some text to an edit control
\r
112 // Append Line Feed
\r
113 int ndx = (int)SendDlgItemMessage(nID, WM_GETTEXTLENGTH, 0, 0);
\r
117 SendDlgItemMessage(nID, EM_SETSEL, (WPARAM)ndx, (LPARAM)ndx);
\r
118 SendDlgItemMessage(nID, EM_REPLACESEL, 0, (LPARAM) (_T( "\r\n")));
\r
122 ndx = (int)SendDlgItemMessage(nID, WM_GETTEXTLENGTH, 0, 0);
\r
123 SendDlgItemMessage(nID, EM_SETSEL, (WPARAM)ndx, (LPARAM)ndx);
\r
124 SendDlgItemMessage(nID, EM_REPLACESEL, 0, (LPARAM) buf);
\r
127 INT_PTR CSvrDialog::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
129 // respond to the user defined message posted to the dialog
\r
135 case USER_DISCONNECT:
\r
136 OnSocketDisconnect((CServerSocket*)wParam);
\r
139 OnSocketReceive((CServerSocket*)wParam);
\r
142 PostQuitMessage(0);
\r
146 // Pass unhandled messages on to parent DialogProc
\r
147 return DialogProcDefault(uMsg, wParam, lParam);
\r
150 void CSvrDialog::LoadCommonControlsEx()
\r
152 // This function adds support for the IP address control in the dialog.
\r
157 // Load the Common Controls DLL
\r
158 hComCtl = ::LoadLibrary(_T("COMCTL32.DLL"));
\r
160 throw CWinException(_T("Failed to load COMCTL32.DLL"));
\r
162 if (GetComCtlVersion() > 470)
\r
164 // Declare a pointer to the InItCommonControlsEx function
\r
165 typedef BOOL WINAPI INIT_EX(INITCOMMONCONTROLSEX*);
\r
166 INIT_EX* pfnInit = (INIT_EX*)::GetProcAddress(hComCtl, "InitCommonControlsEx");
\r
168 // Call InitCommonControlsEx
\r
169 INITCOMMONCONTROLSEX InitStruct;
\r
170 InitStruct.dwSize = sizeof(INITCOMMONCONTROLSEX);
\r
171 InitStruct.dwICC = ICC_INTERNET_CLASSES;
\r
172 if((!(*pfnInit)(&InitStruct)))
\r
173 throw CWinException(_T("InitCommonControlsEx failed"));
\r
177 ::MessageBox(NULL, _T("IP Address Control not supported!"), _T("Error"), MB_OK);
\r
180 ::FreeLibrary(hComCtl);
\r
183 catch (const CWinException &e)
\r
187 ::FreeLibrary(hComCtl);
\r
191 void CSvrDialog::OnSocketDisconnect(CServerSocket* pClient)
\r
193 // Respond to a socket disconnect notification
\r
194 Append(IDC_EDIT_STATUS, _T("Client disconnected"));
\r
197 // Allocate an iterator for our CServerSocket map
\r
198 std::map< ServerSocketPtr, TCPClientDlgPtr >::iterator Iter;
\r
200 for (Iter = m_ConnectedClients.begin(); Iter != m_ConnectedClients.end(); ++Iter)
\r
202 if (Iter->first.get() == pClient)
\r
206 // delete the CServerSocket, and remove its pointer
\r
207 if (Iter != m_ConnectedClients.end())
\r
209 m_ConnectedClients.erase(Iter);
\r
213 BOOL CSvrDialog::OnCommand(WPARAM wParam, LPARAM lParam)
\r
215 UNREFERENCED_PARAMETER(lParam);
\r
217 // Respond to the various dialog buttons
\r
218 switch (LOWORD(wParam))
\r
220 case IDC_BUTTON_START:
\r
223 case IDC_BUTTON_SEND:
\r
226 } //switch (LOWORD(wParam))
\r
231 BOOL CSvrDialog::OnInitDialog()
\r
234 SetIconLarge( IDW_MAIN );
\r
235 SetIconSmall( IDW_MAIN );
\r
237 // reposition dialog
\r
238 CRect rc = GetWindowRect();
\r
239 MoveWindow( rc.left-14, rc.top-14, rc.Width(), rc.Height(), TRUE );
\r
241 // Attach CWnd objects to the dialog's children
\r
242 m_IP4Address.AttachDlgItem( IDC_IPADDRESS, this );
\r
243 m_EditIP6Address.AttachDlgItem( IDC_EDIT_IPV6ADDRESS, this );
\r
244 m_EditStatus.AttachDlgItem( IDC_EDIT_STATUS, this );
\r
245 m_EditPort.AttachDlgItem( IDC_EDIT_PORT, this );
\r
246 m_EditSend.AttachDlgItem( IDC_EDIT_SEND, this );
\r
247 m_EditReceive.AttachDlgItem( IDC_EDIT_RECEIVE, this );
\r
248 m_ButtonStart.AttachDlgItem( IDC_BUTTON_START, this );
\r
249 m_ButtonSend.AttachDlgItem( IDC_BUTTON_SEND, this );
\r
250 m_RadioIP4.AttachDlgItem( IDC_RADIO_IPV4, this );
\r
251 m_RadioIP6.AttachDlgItem( IDC_RADIO_IPV6, this );
\r
252 m_RadioTCP.AttachDlgItem( IDC_RADIO_TCP, this );
\r
253 m_RadioUDP.AttachDlgItem( IDC_RADIO_UDP, this );
\r
255 // Set the initial state of the dialog
\r
256 m_EditIP6Address.SetWindowText( _T("0000:0000:0000:0000:0000:0000:0000:0001") );
\r
257 m_RadioIP4.SendMessage( BM_SETCHECK, BST_CHECKED, 0 );
\r
258 m_IP4Address.SendMessage( IPM_SETADDRESS, 0, MAKEIPADDRESS(127, 0, 0, 1) );
\r
259 m_EditStatus.SetWindowText( _T("Server Stopped") );
\r
260 m_EditPort.SetWindowText( _T("3000") );
\r
261 m_RadioTCP.SendMessage( BM_SETCHECK, BST_CHECKED, 0 );
\r
262 if (!m_MainSocket.IsIPV6Supported())
\r
264 m_RadioIP6.EnableWindow(FALSE);
\r
265 m_EditIP6Address.EnableWindow(FALSE);
\r
271 void CSvrDialog::OnStartServer()
\r
273 // Respond to the Start/Stop Button press
\r
274 TRACE( _T("Start/Stop Button Pressed\n") );
\r
276 if (!m_bServerStarted)
\r
278 // Attempt to start the server
\r
279 if (!StartServer())
\r
282 // Update the dialog
\r
283 m_ButtonStart.SetWindowText( _T("Stop Server") );
\r
284 m_IP4Address.EnableWindow(FALSE);
\r
285 m_EditIP6Address.EnableWindow(FALSE);
\r
286 m_EditPort.EnableWindow(FALSE);
\r
287 m_RadioIP4.EnableWindow(FALSE);
\r
288 m_RadioIP6.EnableWindow(FALSE);
\r
289 m_RadioTCP.EnableWindow(FALSE);
\r
290 m_RadioUDP.EnableWindow(FALSE);
\r
293 if (m_SocketType == SOCK_STREAM)
\r
295 Append(IDC_EDIT_STATUS, _T("TCP Server Started"));
\r
296 Append(IDC_EDIT_STATUS, _T("Waiting for client ..."));
\r
300 Append(IDC_EDIT_STATUS, _T("UDP Server Started"));
\r
301 Append(IDC_EDIT_STATUS, _T("Waiting for client data"));
\r
308 // Update the dialog
\r
309 Append(IDC_EDIT_STATUS, _T("Server Stopped"));
\r
310 m_ButtonStart.SetWindowText( _T("Start Server") );
\r
311 m_IP4Address.EnableWindow(TRUE);
\r
312 m_EditPort.EnableWindow(TRUE);
\r
313 m_RadioIP4.EnableWindow(TRUE);
\r
314 m_RadioTCP.EnableWindow(TRUE);
\r
315 m_RadioUDP.EnableWindow(TRUE);
\r
316 m_ButtonSend.EnableWindow(FALSE);
\r
317 m_EditSend.EnableWindow(FALSE);
\r
318 if (m_MainSocket.IsIPV6Supported())
\r
320 m_RadioIP6.EnableWindow(TRUE);
\r
321 m_EditIP6Address.EnableWindow(TRUE);
\r
324 m_bServerStarted = !m_bServerStarted;
\r
327 void CSvrDialog::OnSend()
\r
329 // Responds to the send button
\r
331 switch(m_SocketType)
\r
334 // TCP connections have a seperate chat dialog for sending/receiving data
\r
338 CString sSend = m_EditSend.GetWindowText();
\r
339 m_MainSocket.SendTo(sSend, lstrlen(sSend), 0, (LPSOCKADDR)&m_saUDPClient, sizeof(m_saUDPClient));
\r
345 void CSvrDialog::OnSocketAccept()
\r
347 // Accept the connection from the client
\r
348 ServerSocketPtr pClient = new CServerSocket;
\r
349 m_MainSocket.Accept(*pClient, NULL, NULL);
\r
350 if (INVALID_SOCKET == m_MainSocket.GetSocket())
\r
352 TRACE(_T("Failed to accept connection from client\n"));
\r
353 TRACE(m_MainSocket.GetLastError());
\r
357 pClient->StartEvents();
\r
359 // Create the new chat dialog
\r
360 TCPClientDlgPtr pDialog = new CTCPClientDlg(IDD_CHAT, this);
\r
361 pDialog->m_pSocket = pClient;
\r
362 pDialog->DoModeless();
\r
364 // Reposition the chat dialog
\r
365 CRect rc = pDialog->GetWindowRect();
\r
366 int offset = 4 * ((int)m_ConnectedClients.size() - 1);
\r
367 pDialog->MoveWindow(rc.left + offset, rc.top + offset + 80, rc.Width(), rc.Height(), TRUE);
\r
368 pDialog->ShowWindow();
\r
370 // Add the socket and dialog to the map
\r
371 m_ConnectedClients.insert(std::make_pair(pClient, pDialog));
\r
373 // Update the dialog
\r
374 Append(IDC_EDIT_STATUS, _T("Client Connected"));
\r
377 void CSvrDialog::OnSocketReceive(CServerSocket* pClient)
\r
379 std::vector<TCHAR> vTChar(1025, _T('\0'));
\r
380 TCHAR* bufArray = &vTChar.front(); // TCHAR array with 1025 elements
\r
382 switch (m_SocketType)
\r
386 // Pass this on to the TCP chat dialog
\r
387 std::map< ServerSocketPtr, TCPClientDlgPtr >::iterator Iter;
\r
389 for (Iter = m_ConnectedClients.begin(); Iter != m_ConnectedClients.end(); ++Iter)
\r
391 if (Iter->first.get() == pClient)
\r
395 if (Iter != m_ConnectedClients.end() )
\r
396 Iter->second->Receive();
\r
401 int addrlen = sizeof(m_saUDPClient);
\r
402 m_MainSocket.ReceiveFrom(bufArray, 1024, 0, (LPSOCKADDR)&m_saUDPClient, &addrlen);
\r
403 TRACE(_T("[Received:] ")); TRACE(bufArray); TRACE(_T("\n"));
\r
404 m_ButtonSend.EnableWindow(TRUE);
\r
405 m_EditSend.EnableWindow(TRUE);
\r
406 SendMessage( WM_NEXTDLGCTL, (WPARAM)GetDlgItem(IDC_EDIT_SEND), TRUE );
\r
410 Append(IDC_EDIT_RECEIVE, bufArray);
\r
413 BOOL CSvrDialog::StartServer()
\r
415 LRESULT lr = m_RadioTCP.SendMessage( BM_GETCHECK, 0, 0 );
\r
416 m_SocketType = (lr == BST_CHECKED)? SOCK_STREAM : SOCK_DGRAM ;
\r
418 // Create the main socket
\r
419 lr = m_RadioIP4.SendMessage( BM_GETCHECK, 0, 0 );
\r
420 int IPfamily = (lr == BST_CHECKED)? PF_INET : PF_INET6 ;
\r
421 if (!m_MainSocket.Create(IPfamily, m_SocketType))
\r
423 Append(IDC_EDIT_STATUS, _T("Create Socket Failed"));
\r
424 Append(IDC_EDIT_STATUS, m_MainSocket.GetLastError());
\r
428 // Retrieve the IP Address
\r
430 if (PF_INET6 == IPfamily)
\r
432 strAddr = m_EditIP6Address.GetWindowText();
\r
437 m_IP4Address.SendMessage( IPM_GETADDRESS, 0, (LPARAM) (LPDWORD) &dwAddr );
\r
438 in_addr addr = {0};
\r
439 addr.S_un.S_addr = htonl(dwAddr);
\r
440 strAddr = A2T( inet_ntoa(addr) );
\r
443 // Retrieve the local port number
\r
444 CString strPort = m_EditPort.GetWindowText();
\r
446 // Bind to the socket
\r
447 Append(IDC_EDIT_STATUS, _T("Binding to socket"));
\r
449 str.Format( _T("Addr %s, Port %s, type %s"), strAddr.c_str(), strPort.c_str(), (m_SocketType == SOCK_STREAM)?_T("TCP"):_T("UDP") );
\r
450 Append(IDC_EDIT_STATUS, str);
\r
452 int RetVal = m_MainSocket.Bind( strAddr, strPort );
\r
455 Append(IDC_EDIT_STATUS, _T("Bind failed"));
\r
456 Append(IDC_EDIT_STATUS, m_MainSocket.GetLastError());
\r
460 if (m_SocketType == SOCK_STREAM)
\r
462 // Listen for connections from clients (TCP server only)
\r
463 RetVal = m_MainSocket.Listen();
\r
464 if ( SOCKET_ERROR == RetVal )
\r
466 Append(IDC_EDIT_STATUS, _T("Error listening on socket"));
\r
467 Append(IDC_EDIT_STATUS, m_MainSocket.GetLastError());
\r
472 m_MainSocket.StartEvents();
\r
477 void CSvrDialog::StopServer()
\r
479 m_MainSocket.Disconnect();
\r
480 m_ConnectedClients.clear();
\r