]> git.saurik.com Git - wxWidgets.git/blame - samples/wxsocket/client.cpp
Applied Diana's font patch II
[wxWidgets.git] / samples / wxsocket / client.cpp
CommitLineData
f85d901f
GRG
1/////////////////////////////////////////////////////////////////////////////
2// Name: client.cpp
3// Purpose: Client for wxSocket demo
4// Author: Guillermo Rodriguez Garcia <guille@iies.es>
5// Modified by:
6// Created: 1999/09/19
7// RCS-ID: $Id$
8// Copyright: (c) 1999 Guillermo Rodriguez Garcia
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ==========================================================================
13// declarations
14// ==========================================================================
15
16// --------------------------------------------------------------------------
17// headers
18// --------------------------------------------------------------------------
e2a6f233 19
f4ada568 20#ifdef __GNUG__
f85d901f
GRG
21# pragma implementation "client.cpp"
22# pragma interface "client.cpp"
f4ada568
GL
23#endif
24
f85d901f 25// For compilers that support precompilation, includes "wx/wx.h".
f4ada568
GL
26#include "wx/wxprec.h"
27
28#ifdef __BORLANDC__
f85d901f 29# pragma hdrstop
f4ada568
GL
30#endif
31
f85d901f 32// for all others, include the necessary headers
f4ada568 33#ifndef WX_PRECOMP
f85d901f
GRG
34# include "wx/wx.h"
35# include "wx/socket.h"
36# include "wx/url.h"
37# include "wx/protocol/http.h"
38# include "wx/progdlg.h"
f4ada568 39#endif
e2a6f233 40
f85d901f
GRG
41// --------------------------------------------------------------------------
42// resources
43// --------------------------------------------------------------------------
f4ada568 44
f85d901f
GRG
45// the application icon
46#if defined(__WXGTK__) || defined(__WXMOTIF__)
47# include "mondrian.xpm"
e2a6f233
JS
48#endif
49
f85d901f
GRG
50// --------------------------------------------------------------------------
51// classes
52// --------------------------------------------------------------------------
f4ada568 53
f85d901f
GRG
54// Define a new application type
55class MyApp : public wxApp
56{
f4ada568 57public:
f85d901f 58 virtual bool OnInit();
f4ada568
GL
59};
60
f85d901f
GRG
61// Define a new frame type: this is going to be our main frame
62class MyFrame : public wxFrame
f4ada568
GL
63{
64public:
f85d901f
GRG
65 MyFrame();
66 ~MyFrame();
67
68 // event handlers (these functions should _not_ be virtual)
69 void OnQuit(wxCommandEvent& event);
70 void OnAbout(wxCommandEvent& event);
71 void OnOpenConnection(wxCommandEvent& event);
72 void OnTest1(wxCommandEvent& event);
73 void OnTest2(wxCommandEvent& event);
74 void OnTest3(wxCommandEvent& event);
75 void OnCloseConnection(wxCommandEvent& event);
76 void OnSocketEvent(wxSocketEvent& event);
77
78 // convenience functions
79 void UpdateStatusBar();
80
81private:
82 wxSocketClient *m_sock;
83 wxPanel *m_panel;
84 wxTextCtrl *m_text;
85 wxMenu *m_menuFile;
86 wxMenu *m_menuSocket;
87 wxMenuBar *m_menuBar;
88 bool m_busy;
89
90 // any class wishing to process wxWindows events must use this macro
91 DECLARE_EVENT_TABLE()
f4ada568
GL
92};
93
f85d901f
GRG
94// --------------------------------------------------------------------------
95// constants
96// --------------------------------------------------------------------------
f4ada568 97
f85d901f
GRG
98// IDs for the controls and the menu commands
99enum
f4ada568 100{
f85d901f
GRG
101 // menu items
102 CLIENT_QUIT = 1000,
103 CLIENT_ABOUT,
104 CLIENT_OPEN,
105 CLIENT_TEST1,
106 CLIENT_TEST2,
107 CLIENT_TEST3,
108 CLIENT_CLOSE,
109
110 // id for socket
111 SOCKET_ID
112};
f4ada568 113
f85d901f
GRG
114// --------------------------------------------------------------------------
115// event tables and other macros for wxWindows
116// --------------------------------------------------------------------------
f4ada568 117
f85d901f
GRG
118BEGIN_EVENT_TABLE(MyFrame, wxFrame)
119 EVT_MENU(CLIENT_QUIT, MyFrame::OnQuit)
120 EVT_MENU(CLIENT_ABOUT, MyFrame::OnAbout)
121 EVT_MENU(CLIENT_OPEN, MyFrame::OnOpenConnection)
122 EVT_MENU(CLIENT_TEST1, MyFrame::OnTest1)
123 EVT_MENU(CLIENT_TEST2, MyFrame::OnTest2)
124 EVT_MENU(CLIENT_TEST3, MyFrame::OnTest3)
125 EVT_MENU(CLIENT_CLOSE, MyFrame::OnCloseConnection)
126 EVT_SOCKET(SOCKET_ID, MyFrame::OnSocketEvent)
127END_EVENT_TABLE()
f4ada568 128
f85d901f 129IMPLEMENT_APP(MyApp)
f4ada568 130
f85d901f
GRG
131// ==========================================================================
132// implementation
133// ==========================================================================
f4ada568 134
f85d901f
GRG
135// --------------------------------------------------------------------------
136// the application class
137// --------------------------------------------------------------------------
f4ada568 138
f85d901f
GRG
139bool MyApp::OnInit()
140{
141 // Create the main application window
142 MyFrame *frame = new MyFrame();
f4ada568 143
f85d901f 144 // Show it and tell the application that it's our main window
f4ada568 145 frame->Show(TRUE);
f85d901f
GRG
146 SetTopWindow(frame);
147
148 // success
27529614 149 return TRUE;
f4ada568
GL
150}
151
f85d901f
GRG
152// --------------------------------------------------------------------------
153// main frame
154// --------------------------------------------------------------------------
155
156// frame constructor
157MyFrame::MyFrame() : wxFrame((wxFrame *)NULL, -1,
158 _T("wxSocket demo: Client"),
159 wxDefaultPosition, wxSize(300, 200))
f4ada568 160{
f85d901f
GRG
161 // Give the frame an icon
162 SetIcon(wxICON(mondrian));
163
164 // Make menus
165 m_menuFile = new wxMenu();
166 m_menuFile->Append(CLIENT_ABOUT, _T("&About...\tCtrl-A"), _T("Show about dialog"));
167 m_menuFile->AppendSeparator();
168 m_menuFile->Append(CLIENT_QUIT, _T("E&xit\tAlt-X"), _T("Quit client"));
169
170 m_menuSocket = new wxMenu();
171 m_menuSocket->Append(CLIENT_OPEN, _T("&Open session"), _T("Connect to server"));
172 m_menuSocket->AppendSeparator();
173 m_menuSocket->Append(CLIENT_TEST1, _T("Test &1"), _T("Test basic functionality"));
174 m_menuSocket->Append(CLIENT_TEST2, _T("Test &2"), _T("Test ReadMsg and WriteMsg"));
175 m_menuSocket->Append(CLIENT_TEST3, _T("Test &3"), _T("Test large data transfer"));
176 m_menuSocket->AppendSeparator();
177 m_menuSocket->Append(CLIENT_CLOSE, _T("&Close session"), _T("Close connection"));
178
179 // Append menus to the menubar
180 m_menuBar = new wxMenuBar();
181 m_menuBar->Append(m_menuFile, _T("&File"));
182 m_menuBar->Append(m_menuSocket, _T("&Socket"));
183 SetMenuBar(m_menuBar);
184
185 // Status bar
f4ada568 186 CreateStatusBar(2);
f85d901f
GRG
187
188 // Make a panel with a textctrl in it
189 m_panel = new wxPanel(this, -1, wxPoint(0, 0), GetClientSize());
190 m_text = new wxTextCtrl(m_panel, -1,
191 _T("Welcome to wxSocket demo: Client\n")
192 _T("Client ready\n\n"),
193 wxPoint(0, 0), m_panel->GetClientSize(),
194 wxTE_MULTILINE | wxTE_READONLY);
195
196 // Create the socket
197 m_sock = new wxSocketClient();
198 m_sock->SetEventHandler(*this, SOCKET_ID);
199 m_sock->SetNotify(wxSOCKET_CONNECTION_FLAG |
200 wxSOCKET_INPUT_FLAG |
201 wxSOCKET_LOST_FLAG);
202 m_sock->Notify(TRUE);
203
204 m_busy = FALSE;
205 UpdateStatusBar();
f4ada568
GL
206}
207
208MyFrame::~MyFrame()
209{
f85d901f 210 delete m_sock;
f4ada568
GL
211}
212
f85d901f
GRG
213// event handlers
214
215void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
f4ada568 216{
f85d901f 217 // TRUE is to force the frame to close
f4ada568
GL
218 Close(TRUE);
219}
220
f85d901f
GRG
221void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
222{
223 wxMessageBox(_T("wxSocket demo: Client\n")
224 _T("(c) 1999 Guillermo Rodriguez Garcia\n"),
225 _T("About Client"),
226 wxOK | wxICON_INFORMATION, this);
227}
228
229void MyFrame::OnOpenConnection(wxCommandEvent& WXUNUSED(event))
f4ada568
GL
230{
231 wxIPV4address addr;
f4ada568 232
f85d901f
GRG
233 m_menuSocket->Enable(CLIENT_OPEN, FALSE);
234 m_menuSocket->Enable(CLIENT_CLOSE, FALSE);
235
236 // Ask server address
237 wxString hostname = wxGetTextFromUser(
238 _T("Enter the address of the wxSocket demo server:"),
239 _T("Connect ..."),
240 _T("localhost"));
241
242 addr.Hostname(hostname);
f4ada568 243 addr.Service(3000);
f4ada568 244
f85d901f
GRG
245 // Non-blocking connect
246 m_text->AppendText(_T("Trying to connect (timeout = 10 sec) ...\n"));
247 m_sock->Connect(addr, FALSE);
248 m_sock->WaitOnConnect(10);
249
250 if (m_sock->IsConnected())
251 m_text->AppendText(_T("Succeeded ! Connection established\n"));
252 else
253 {
254 m_sock->Close();
255 m_text->AppendText(_T("Failed ! Unable to connect\n"));
256 wxMessageBox(_T("Can't connect to the specified host"), _T("Alert !"));
257 }
258
259 UpdateStatusBar();
f4ada568
GL
260}
261
f85d901f 262void MyFrame::OnTest1(wxCommandEvent& WXUNUSED(event))
f4ada568 263{
f85d901f
GRG
264 char *buf1, *buf2;
265 char len;
266
267 // Disable socket menu entries (exception: Close Session)
268 m_busy = TRUE;
269 UpdateStatusBar();
270
271 m_text->AppendText(_T("\n=== Test 1 begins ===\n"));
272
273 // Tell the server which test we are running
274 char c = 0xBE;
275 m_sock->Write(&c, 1);
276
277 // Send some data and read it back. We know the size of the
278 // buffer, so we can specify the exact number of bytes to be
279 // sent or received and use the WAITALL flag. Also, we have
280 // disabled menu entries which could interfere with the test,
281 // so we can safely avoid the BLOCK (formerly SPEED) flag.
282 //
283 // First we send a byte with the length of the string, then
284 // we send the string itself (do NOT try to send any integral
285 // value larger than a byte "as is" acrosss the network, or
286 // you might be in trouble! Ever heard about big and little
287 // endian computers?)
288 //
289 m_sock->SetFlags(wxSOCKET_WAITALL);
290
291 buf1 = _T("Test string (less than 127 chars!)");
292 len = wxStrlen(buf1) + 1;
293 buf2 = new char[len];
294
295 m_text->AppendText(_T("Sending a test buffer to the server ..."));
296 m_sock->Write(&len, 1);
297 m_sock->Write(buf1, len);
298 m_text->AppendText(m_sock->Error() ? _T("failed !\n") : _T("done\n"));
299
300 m_text->AppendText(_T("Receiving the buffer back from server ..."));
301 m_sock->Read(buf2, len);
302 m_text->AppendText(m_sock->Error() ? _T("failed !\n") : _T("done\n"));
303
304 m_text->AppendText(_T("Comparing the two buffers ..."));
305 if (memcmp(buf1, buf2, len) != 0)
306 {
307 m_text->AppendText(_T("failed!\n"));
308 m_text->AppendText(_T("Test 1 failed !\n"));
309 }
310 else
311 {
312 m_text->AppendText(_T("done\n"));
313 m_text->AppendText(_T("Test 1 passed !\n"));
314 }
315 m_text->AppendText(_T("=== Test 1 ends ===\n"));
f4ada568 316
f85d901f
GRG
317 delete[] buf2;
318 m_busy = FALSE;
319 UpdateStatusBar();
320}
f4ada568 321
f85d901f
GRG
322void MyFrame::OnTest2(wxCommandEvent& WXUNUSED(event))
323{
324 char *msg1;
325 char *msg2;
326 size_t len;
327
328 // Disable socket menu entries (exception: Close Session)
329 m_busy = TRUE;
330 UpdateStatusBar();
331
332 m_text->AppendText(_T("\n=== Test 2 begins ===\n"));
333
334 // Tell the server which test we are running
335 char c = 0xCE;
336 m_sock->Write(&c, 1);
337
338 // Here we use ReadMsg and WriteMsg to send messages with
339 // a header with size information. Also, the reception is
340 // event triggered, so we test input events as well.
341 //
342 // We need to set no flags here (ReadMsg and WriteMsg are
343 // not affected by flags)
344 //
345 m_sock->SetFlags(wxSOCKET_WAITALL);
346
347 wxString s = wxGetTextFromUser(
348 _T("Enter an arbitrary string to send to the server:"),
349 _T("Test 2 ..."),
350 _T("Yes I like wxWindows!"));
351
352 msg1 = (char *)s.c_str();
353 len = wxStrlen(msg1) + 1;
354 msg2 = (char *)malloc(len);
355
356 m_text->AppendText(_T("Sending the string with WriteMsg ..."));
357 m_sock->WriteMsg(msg1, len);
358 m_text->AppendText(m_sock->Error() ? _T("failed !\n") : _T("done\n"));
359 m_text->AppendText(_T("Waiting for an event (timeout = 2 sec)\n"));
360
361 // Wait until data available (will also return if the connection is lost)
362 m_sock->WaitForRead(2);
363
364 if (m_sock->IsData())
365 {
366 m_text->AppendText(_T("Reading the string back with ReadMsg ..."));
367 m_sock->ReadMsg(msg2, len);
368 m_text->AppendText(m_sock->Error() ? _T("failed !\n") : _T("done\n"));
369 m_text->AppendText(_T("Comparing the two buffers ..."));
370 if (memcmp(msg1, msg2, len) != 0)
371 {
372 m_text->AppendText(_T("failed!\n"));
373 m_text->AppendText(_T("Test 2 failed !\n"));
374 }
375 else
376 {
377 m_text->AppendText(_T("done\n"));
378 m_text->AppendText(_T("Test 2 passed !\n"));
379 }
765e386b 380 }
f85d901f
GRG
381 else
382 m_text->AppendText(_T("Timeout ! Test 2 failed.\n"));
765e386b 383
f85d901f 384 m_text->AppendText(_T("=== Test 2 ends ===\n"));
765e386b 385
f85d901f
GRG
386 free(msg2);
387 m_busy = FALSE;
388 UpdateStatusBar();
765e386b
GL
389}
390
f85d901f 391void MyFrame::OnTest3(wxCommandEvent& WXUNUSED(event))
f4ada568 392{
f85d901f
GRG
393 m_text->AppendText(_T("\n=== Test 3 begins ===\n"));
394 m_text->AppendText(_T("Test 3 not implemented\n"));
395 m_text->AppendText(_T("=== Test 3 ends ===\n"));
f4ada568
GL
396}
397
f85d901f 398void MyFrame::OnCloseConnection(wxCommandEvent& WXUNUSED(event))
f4ada568 399{
f85d901f
GRG
400 m_sock->Close();
401 UpdateStatusBar();
f4ada568
GL
402}
403
f85d901f 404void MyFrame::OnSocketEvent(wxSocketEvent& event)
f4ada568 405{
f85d901f
GRG
406 wxString s = _T("OnSocketEvent: ");
407
408 switch(event.SocketEvent())
409 {
410 case wxSOCKET_INPUT : s.Append(_T("wxSOCKET_INPUT\n")); break;
411 case wxSOCKET_LOST : s.Append(_T("wxSOCKET_LOST\n")); break;
412 case wxSOCKET_CONNECTION : s.Append(_T("wxSOCKET_CONNECTION\n")); break;
413 default : s.Append(_T("Unexpected event !\n")); break;
414 }
f4ada568 415
f85d901f
GRG
416 m_text->AppendText(s);
417 UpdateStatusBar();
f4ada568
GL
418}
419
f85d901f 420// convenience functions
a324a7bc 421
f85d901f 422void MyFrame::UpdateStatusBar()
a324a7bc 423{
f85d901f 424 wxString s;
a324a7bc 425
f85d901f
GRG
426 if (!m_sock->IsConnected())
427 {
428 s.Printf(_T("Not connected"));
a324a7bc 429 }
f85d901f
GRG
430 else
431 {
432 wxIPV4address addr;
a324a7bc 433
f85d901f
GRG
434 m_sock->GetPeer(addr);
435 s.Printf(_T("%s : %d"), (addr.Hostname()).c_str(), addr.Service());
436 }
f4ada568 437
f85d901f 438 SetStatusText(s, 1);
a737331d 439
f85d901f
GRG
440 m_menuSocket->Enable(CLIENT_OPEN, !m_sock->IsConnected() && !m_busy);
441 m_menuSocket->Enable(CLIENT_TEST1, m_sock->IsConnected() && !m_busy);
442 m_menuSocket->Enable(CLIENT_TEST2, m_sock->IsConnected() && !m_busy);
443 m_menuSocket->Enable(CLIENT_TEST3, m_sock->IsConnected() && !m_busy);
444 m_menuSocket->Enable(CLIENT_CLOSE, m_sock->IsConnected());
f4ada568 445}