]>
git.saurik.com Git - wxWidgets.git/blob - samples/sockets/client.cpp
e21a1e2542ef19b355c0a5704538051eb2911159
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Client for wxSocket demo
4 // Author: Guillermo Rodriguez Garcia <guille@iies.es>
8 // Copyright: (c) 1999 Guillermo Rodriguez Garcia
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ==========================================================================
14 // ==========================================================================
16 // --------------------------------------------------------------------------
18 // --------------------------------------------------------------------------
21 # pragma implementation "client.cpp"
22 # pragma interface "client.cpp"
25 // For compilers that support precompilation, includes "wx/wx.h".
26 #include "wx/wxprec.h"
32 // for all others, include the necessary headers
37 #include "wx/socket.h"
39 #include "wx/protocol/http.h"
40 #include "wx/progdlg.h"
42 // --------------------------------------------------------------------------
44 // --------------------------------------------------------------------------
46 // the application icon
47 #if defined(__WXGTK__) || defined(__WXMOTIF__)
48 # include "mondrian.xpm"
51 // --------------------------------------------------------------------------
53 // --------------------------------------------------------------------------
55 // Define a new application type
56 class MyApp
: public wxApp
59 virtual bool OnInit();
62 // Define a new frame type: this is going to be our main frame
63 class MyFrame
: public wxFrame
69 // event handlers (these functions should _not_ be virtual)
70 void OnQuit(wxCommandEvent
& event
);
71 void OnAbout(wxCommandEvent
& event
);
72 void OnOpenConnection(wxCommandEvent
& event
);
73 void OnTest1(wxCommandEvent
& event
);
74 void OnTest2(wxCommandEvent
& event
);
75 void OnTest3(wxCommandEvent
& event
);
76 void OnCloseConnection(wxCommandEvent
& event
);
77 void OnSocketEvent(wxSocketEvent
& event
);
78 void OnDatagram(wxCommandEvent
& event
);
80 // convenience functions
81 void UpdateStatusBar();
84 wxSocketClient
*m_sock
;
89 wxMenu
*m_menuDatagramSocket
;
93 // any class wishing to process wxWindows events must use this macro
97 // --------------------------------------------------------------------------
99 // --------------------------------------------------------------------------
101 // IDs for the controls and the menu commands
118 // --------------------------------------------------------------------------
119 // event tables and other macros for wxWindows
120 // --------------------------------------------------------------------------
122 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
123 EVT_MENU(CLIENT_QUIT
, MyFrame::OnQuit
)
124 EVT_MENU(CLIENT_ABOUT
, MyFrame::OnAbout
)
125 EVT_MENU(CLIENT_OPEN
, MyFrame::OnOpenConnection
)
126 EVT_MENU(CLIENT_TEST1
, MyFrame::OnTest1
)
127 EVT_MENU(CLIENT_TEST2
, MyFrame::OnTest2
)
128 EVT_MENU(CLIENT_TEST3
, MyFrame::OnTest3
)
129 EVT_MENU(CLIENT_CLOSE
, MyFrame::OnCloseConnection
)
130 EVT_MENU(CLIENT_DGRAM
, MyFrame::OnDatagram
)
131 EVT_SOCKET(SOCKET_ID
, MyFrame::OnSocketEvent
)
136 // ==========================================================================
138 // ==========================================================================
140 // --------------------------------------------------------------------------
141 // the application class
142 // --------------------------------------------------------------------------
146 // Create the main application window
147 MyFrame
*frame
= new MyFrame();
149 // Show it and tell the application that it's our main window
157 // --------------------------------------------------------------------------
159 // --------------------------------------------------------------------------
162 MyFrame::MyFrame() : wxFrame((wxFrame
*)NULL
, -1,
163 _T("wxSocket demo: Client"),
164 wxDefaultPosition
, wxSize(300, 200))
166 // Give the frame an icon
167 SetIcon(wxICON(mondrian
));
170 m_menuFile
= new wxMenu();
171 m_menuFile
->Append(CLIENT_ABOUT
, _T("&About...\tCtrl-A"), _T("Show about dialog"));
172 m_menuFile
->AppendSeparator();
173 m_menuFile
->Append(CLIENT_QUIT
, _T("E&xit\tAlt-X"), _T("Quit client"));
175 m_menuSocket
= new wxMenu();
176 m_menuSocket
->Append(CLIENT_OPEN
, _T("&Open session"), _T("Connect to server"));
177 m_menuSocket
->AppendSeparator();
178 m_menuSocket
->Append(CLIENT_TEST1
, _T("Test &1"), _T("Test basic functionality"));
179 m_menuSocket
->Append(CLIENT_TEST2
, _T("Test &2"), _T("Test ReadMsg and WriteMsg"));
180 m_menuSocket
->Append(CLIENT_TEST3
, _T("Test &3"), _T("Test large data transfer"));
181 m_menuSocket
->AppendSeparator();
182 m_menuSocket
->Append(CLIENT_CLOSE
, _T("&Close session"), _T("Close connection"));
184 m_menuDatagramSocket
= new wxMenu();
185 m_menuDatagramSocket
->Append(CLIENT_DGRAM
, _T("Send Datagram"), _("Test UDP sockets"));
187 // Append menus to the menubar
188 m_menuBar
= new wxMenuBar();
189 m_menuBar
->Append(m_menuFile
, _T("&File"));
190 m_menuBar
->Append(m_menuSocket
, _T("&Socket"));
191 m_menuBar
->Append(m_menuDatagramSocket
, _T("&DatagramSocket"));
192 SetMenuBar(m_menuBar
);
197 // Make a panel with a textctrl in it
198 m_panel
= new wxPanel(this, -1, wxPoint(0, 0), GetClientSize());
199 m_text
= new wxTextCtrl(m_panel
, -1,
200 _T("Welcome to wxSocket demo: Client\n")
201 _T("Client ready\n\n"),
202 wxPoint(0, 0), m_panel
->GetClientSize(),
203 wxTE_MULTILINE
| wxTE_READONLY
);
206 m_sock
= new wxSocketClient();
207 m_sock
->SetEventHandler(*this, SOCKET_ID
);
208 m_sock
->SetNotify(wxSOCKET_CONNECTION_FLAG
|
209 wxSOCKET_INPUT_FLAG
|
211 m_sock
->Notify(TRUE
);
224 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
226 // TRUE is to force the frame to close
230 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
232 wxMessageBox(_T("wxSocket demo: Client\n")
233 _T("(c) 1999 Guillermo Rodriguez Garcia\n"),
235 wxOK
| wxICON_INFORMATION
, this);
238 void MyFrame::OnOpenConnection(wxCommandEvent
& WXUNUSED(event
))
242 m_menuSocket
->Enable(CLIENT_OPEN
, FALSE
);
243 m_menuSocket
->Enable(CLIENT_CLOSE
, FALSE
);
245 // Ask server address
246 wxString hostname
= wxGetTextFromUser(
247 _T("Enter the address of the wxSocket demo server:"),
251 addr
.Hostname(hostname
);
254 // Non-blocking connect
255 m_text
->AppendText(_T("Trying to connect (timeout = 10 sec) ...\n"));
256 m_sock
->Connect(addr
, TRUE
);
257 // m_sock->WaitOnConnect(10);
259 if (m_sock
->IsConnected())
260 m_text
->AppendText(_T("Succeeded ! Connection established\n"));
264 m_text
->AppendText(_T("Failed ! Unable to connect\n"));
265 wxMessageBox(_T("Can't connect to the specified host"), _T("Alert !"));
271 void MyFrame::OnTest1(wxCommandEvent
& WXUNUSED(event
))
277 // Disable socket menu entries (exception: Close Session)
281 m_text
->AppendText(_T("\n=== Test 1 begins ===\n"));
283 // Tell the server which test we are running
285 m_sock
->Write(&c
, 1);
287 // Send some data and read it back. We know the size of the
288 // buffer, so we can specify the exact number of bytes to be
289 // sent or received and use the wxSOCKET_WAITALL flag. Also,
290 // we have disabled menu entries which could interfere with
291 // the test, so we can safely avoid the wxSOCKET_BLOCK flag.
293 // First we send a byte with the length of the string, then
294 // we send the string itself (do NOT try to send any integral
295 // value larger than a byte "as is" across the network, or
296 // you might be in trouble! Ever heard about big and little
297 // endian computers?)
299 m_sock
->SetFlags(wxSOCKET_WAITALL
);
301 buf1
= _T("Test string (less than 256 chars!)");
302 len
= wxStrlen(buf1
) + 1;
303 buf2
= new char[len
];
305 m_text
->AppendText(_T("Sending a test buffer to the server ..."));
306 m_sock
->Write((char *)&len
, 1);
307 m_sock
->Write(buf1
, len
);
308 m_text
->AppendText(m_sock
->Error() ? _T("failed !\n") : _T("done\n"));
310 m_text
->AppendText(_T("Receiving the buffer back from server ..."));
311 m_sock
->Read(buf2
, len
);
312 m_text
->AppendText(m_sock
->Error() ? _T("failed !\n") : _T("done\n"));
314 m_text
->AppendText(_T("Comparing the two buffers ..."));
315 if (memcmp(buf1
, buf2
, len
) != 0)
317 m_text
->AppendText(_T("failed!\n"));
318 m_text
->AppendText(_T("Test 1 failed !\n"));
322 m_text
->AppendText(_T("done\n"));
323 m_text
->AppendText(_T("Test 1 passed !\n"));
325 m_text
->AppendText(_T("=== Test 1 ends ===\n"));
332 void MyFrame::OnTest2(wxCommandEvent
& WXUNUSED(event
))
338 // Disable socket menu entries (exception: Close Session)
342 m_text
->AppendText(_T("\n=== Test 2 begins ===\n"));
344 // Tell the server which test we are running
346 m_sock
->Write(&c
, 1);
348 // Here we use ReadMsg and WriteMsg to send messages with
349 // a header with size information. Also, the reception is
350 // event triggered, so we test input events as well.
352 // We need to set no flags here (ReadMsg and WriteMsg are
353 // not affected by flags)
355 m_sock
->SetFlags(wxSOCKET_WAITALL
);
357 wxString s
= wxGetTextFromUser(
358 _T("Enter an arbitrary string to send to the server:"),
360 _T("Yes I like wxWindows!"));
362 msg1
= (char *)s
.c_str();
363 len
= wxStrlen(msg1
) + 1;
364 msg2
= new char[len
];
366 m_text
->AppendText(_T("Sending the string with WriteMsg ..."));
367 m_sock
->WriteMsg(msg1
, len
);
368 m_text
->AppendText(m_sock
->Error() ? _T("failed !\n") : _T("done\n"));
369 m_text
->AppendText(_T("Waiting for an event (timeout = 2 sec)\n"));
371 // Wait until data available (will also return if the connection is lost)
372 m_sock
->WaitForRead(2);
374 if (m_sock
->IsData())
376 m_text
->AppendText(_T("Reading the string back with ReadMsg ..."));
377 m_sock
->ReadMsg(msg2
, len
);
378 m_text
->AppendText(m_sock
->Error() ? _T("failed !\n") : _T("done\n"));
379 m_text
->AppendText(_T("Comparing the two buffers ..."));
380 if (memcmp(msg1
, msg2
, len
) != 0)
382 m_text
->AppendText(_T("failed!\n"));
383 m_text
->AppendText(_T("Test 2 failed !\n"));
387 m_text
->AppendText(_T("done\n"));
388 m_text
->AppendText(_T("Test 2 passed !\n"));
392 m_text
->AppendText(_T("Timeout ! Test 2 failed.\n"));
394 m_text
->AppendText(_T("=== Test 2 ends ===\n"));
401 void MyFrame::OnTest3(wxCommandEvent
& WXUNUSED(event
))
407 // Disable socket menu entries (exception: Close Session)
411 m_text
->AppendText(_T("\n=== Test 3 begins ===\n"));
413 // Tell the server which test we are running
415 m_sock
->Write(&c
, 1);
417 // This test also is similar to the first one but it sends a
418 // large buffer so that wxSocket is actually forced to split
419 // it into pieces and take care of sending everything before
422 m_sock
->SetFlags(wxSOCKET_WAITALL
);
424 // Note that len is in kbytes here!
426 buf1
= new char[len
* 1024];
427 buf2
= new char[len
* 1024];
429 for (int i
= 0; i
< len
* 1024; i
++)
430 buf1
[i
] = (char)(i
% 256);
432 m_text
->AppendText(_T("Sending a large buffer (32K) to the server ..."));
433 m_sock
->Write((char *)&len
, 1);
434 m_sock
->Write(buf1
, len
* 1024);
435 m_text
->AppendText(m_sock
->Error() ? _T("failed !\n") : _T("done\n"));
437 m_text
->AppendText(_T("Receiving the buffer back from server ..."));
438 m_sock
->Read(buf2
, len
* 1024);
439 m_text
->AppendText(m_sock
->Error() ? _T("failed !\n") : _T("done\n"));
441 m_text
->AppendText(_T("Comparing the two buffers ..."));
442 if (memcmp(buf1
, buf2
, len
) != 0)
444 m_text
->AppendText(_T("failed!\n"));
445 m_text
->AppendText(_T("Test 3 failed !\n"));
449 m_text
->AppendText(_T("done\n"));
450 m_text
->AppendText(_T("Test 3 passed !\n"));
452 m_text
->AppendText(_T("=== Test 3 ends ===\n"));
459 void MyFrame::OnCloseConnection(wxCommandEvent
& WXUNUSED(event
))
465 void MyFrame::OnDatagram(wxCommandEvent
& WXUNUSED(event
))
469 void MyFrame::OnSocketEvent(wxSocketEvent
& event
)
471 wxString s
= _T("OnSocketEvent: ");
473 switch(event
.SocketEvent())
475 case wxSOCKET_INPUT
: s
.Append(_T("wxSOCKET_INPUT\n")); break;
476 case wxSOCKET_LOST
: s
.Append(_T("wxSOCKET_LOST\n")); break;
477 case wxSOCKET_CONNECTION
: s
.Append(_T("wxSOCKET_CONNECTION\n")); break;
478 default : s
.Append(_T("Unexpected event !\n")); break;
481 m_text
->AppendText(s
);
485 // convenience functions
487 void MyFrame::UpdateStatusBar()
491 if (!m_sock
->IsConnected())
493 s
.Printf(_T("Not connected"));
499 m_sock
->GetPeer(addr
);
500 s
.Printf(_T("%s : %d"), (addr
.Hostname()).c_str(), addr
.Service());
505 m_menuSocket
->Enable(CLIENT_OPEN
, !m_sock
->IsConnected() && !m_busy
);
506 m_menuSocket
->Enable(CLIENT_TEST1
, m_sock
->IsConnected() && !m_busy
);
507 m_menuSocket
->Enable(CLIENT_TEST2
, m_sock
->IsConnected() && !m_busy
);
508 m_menuSocket
->Enable(CLIENT_TEST3
, m_sock
->IsConnected() && !m_busy
);
509 m_menuSocket
->Enable(CLIENT_CLOSE
, m_sock
->IsConnected());