]> git.saurik.com Git - wxWidgets.git/blob - samples/wxsocket/client.cpp
Ops. wxUSE_XXX and wxUSE_STREAMS are separated again :-)
[wxWidgets.git] / samples / wxsocket / client.cpp
1 /*
2 * File: client.cpp
3 * Purpose: wxSocket: client demo
4 * Author: LAVAUX Guilhem
5 * Created: June 1997
6 * CVS ID: $Id$
7 * Copyright: (c) 1997, LAVAUX Guilhem
8 */
9
10 #ifdef __GNUG__
11 #pragma implementation
12 #pragma interface
13 #endif
14
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
17
18 #ifdef __BORLANDC__
19 #pragma hdrstop
20 #endif
21
22 #ifndef WX_PRECOMP
23 #include "wx/wx.h"
24 #endif
25
26 #include "wx/wfstream.h"
27 #include "wx/socket.h"
28 #include "wx/url.h"
29 #include "wx/protocol/http.h"
30 #include "wx/thread.h"
31 #include "wx/progdlg.h"
32
33 #if defined(__WXMOTIF__) || defined(__WXGTK__)
34 #include "mondrian.xpm"
35 #endif
36
37 // Define a new application type
38 class MyApp: public wxApp
39 { public:
40 virtual bool OnInit(void);
41 };
42
43 class MyClient;
44
45 // Define a new frame type
46 class MyFrame: public wxFrame
47 {
48 DECLARE_CLASS(MyFrame)
49 public:
50 MyClient *sock;
51 int m_good;
52
53 MyFrame(void);
54 virtual ~MyFrame();
55 void OnCloseTest(wxCommandEvent& evt);
56 void OnExecTest1(wxCommandEvent& evt);
57 void OnExecUrlTest(wxCommandEvent& evt);
58 void OnQuitApp(wxCommandEvent& evt);
59 void OnExecOpenConnection(wxCommandEvent& evt);
60 void OnExecCloseConnection(wxCommandEvent& evt);
61 void OnSocketEvent(wxSocketEvent& evt);
62 void UpdateStatus();
63
64 void Download(wxInputStream *input);
65
66 DECLARE_EVENT_TABLE()
67 };
68
69
70 IMPLEMENT_CLASS(MyFrame, wxFrame)
71
72 /*
73 * Define a new derived SocketClient
74 */
75 class MyClient: public wxSocketClient
76 {
77 public:
78 MyFrame *frame;
79
80 void OnNotify(GSocketEventFlags WXUNUSED(flags)) { frame->UpdateStatus(); }
81 };
82
83 // ID for the menu quit command
84 const int SKDEMO_QUIT = 101;
85 const int SKDEMO_CONNECT = 102;
86 const int SKDEMO_TEST1 = 103;
87 const int SKDEMO_TEST2 = 104;
88 const int SKDEMO_CLOSE = 105;
89 const int SKDEMO_TEST3 = 106;
90 const int ID_TEST_CLOSE = 107;
91 const int SKDEMO_SCK = 108;
92
93 IMPLEMENT_APP(MyApp)
94
95 /*
96 * `Main program' equivalent, creating windows and returning main app frame
97 */
98 bool MyApp::OnInit(void)
99 {
100 // Create the main frame window
101 MyFrame *frame = new MyFrame();
102
103 // Give it an icon
104 frame->SetIcon(wxICON(mondrian));
105
106 // Make a menubar
107 wxMenu *file_menu = new wxMenu();
108
109 file_menu->Append(SKDEMO_QUIT, "Exit");
110 wxMenuBar *menu_bar = new wxMenuBar;
111 menu_bar->Append(file_menu, "File");
112
113 wxMenu *socket_menu = new wxMenu();
114 socket_menu->Append(SKDEMO_CONNECT, "Open session");
115 socket_menu->AppendSeparator();
116 socket_menu->Append(SKDEMO_TEST1, "Start test 1");
117 socket_menu->AppendSeparator();
118 socket_menu->Append(SKDEMO_CLOSE, "Close session");
119 socket_menu->AppendSeparator();
120 socket_menu->Append(SKDEMO_TEST3, "Start URL test");
121
122 menu_bar->Append(socket_menu, "Socket");
123
124 frame->SetMenuBar(menu_bar);
125
126 // Make a panel with a message
127 (void)new wxPanel(frame, -1, wxPoint(0, 0), wxSize(300, 100));
128
129 // Show the frame
130 frame->Show(TRUE);
131
132 // Return the main frame window
133 return TRUE;
134 }
135
136 /*
137 * MyFrame Constructor
138 */
139 MyFrame::MyFrame():
140 wxFrame(NULL, -1, "wxSocket client demo",
141 wxDefaultPosition, wxSize(300, 200), wxDEFAULT_FRAME_STYLE)
142 {
143 sock = new MyClient();
144 sock->SetFlags((wxSocketBase::wxSockFlags) (wxSocketBase::WAITALL | wxSocketBase::SPEED));
145 sock->frame = this;
146 sock->SetNotify(wxSOCKET_LOST_FLAG);
147 CreateStatusBar(2);
148 UpdateStatus();
149 }
150
151 MyFrame::~MyFrame()
152 {
153 delete sock;
154 }
155
156 void MyFrame::OnQuitApp(wxCommandEvent& WXUNUSED(evt))
157 {
158 Close(TRUE);
159 }
160
161 void MyFrame::OnExecOpenConnection(wxCommandEvent& WXUNUSED(evt))
162 {
163 wxIPV4address addr;
164
165 if (sock->IsConnected())
166 sock->Close();
167
168 wxString hname = wxGetTextFromUser("Enter the address of the wxSocket Sample Server",
169 "Connect ...", "localhost");
170 addr.Hostname(hname);
171 addr.Service(3000);
172 sock->SetNotify(wxSOCKET_CONNECTION_FLAG | wxSOCKET_LOST_FLAG);
173 sock->SetNotify(TRUE);
174 sock->Connect(addr, FALSE);
175 sock->WaitOnConnect(10);
176 sock->SetFlags(wxSocketBase::NONE);
177 if (!sock->IsConnected())
178 wxMessageBox("Can't connect to the specified host", "Alert !");
179
180 UpdateStatus();
181 }
182
183 void MyFrame::OnExecCloseConnection(wxCommandEvent& WXUNUSED(evt))
184 {
185 sock->Close();
186 UpdateStatus();
187 }
188
189 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
190 EVT_BUTTON(ID_TEST_CLOSE, MyFrame::OnCloseTest)
191 EVT_MENU(SKDEMO_TEST1, MyFrame::OnExecTest1)
192 EVT_MENU(SKDEMO_TEST3, MyFrame::OnExecUrlTest)
193 EVT_MENU(SKDEMO_QUIT, MyFrame::OnQuitApp)
194 EVT_MENU(SKDEMO_CONNECT, MyFrame::OnExecOpenConnection)
195 EVT_MENU(SKDEMO_CLOSE, MyFrame::OnExecCloseConnection)
196 EVT_SOCKET(SKDEMO_SCK, MyFrame::OnSocketEvent)
197 END_EVENT_TABLE()
198
199 class MyFrameSocketTimer: public wxTimer {
200 public:
201 void Notify() {
202 *m_var = 0;
203 }
204
205 int *m_var;
206 };
207
208 void MyFrame::OnSocketEvent(wxSocketEvent& evt)
209 {
210 m_good = 1;
211 }
212
213 void MyFrame::OnCloseTest(wxCommandEvent& evt)
214 {
215 wxButton *button = (wxButton *)evt.GetEventObject();
216 wxDialog *dlg = (wxDialog *)button->GetParent();
217
218 dlg->EndModal(0);
219 }
220
221 void MyFrame::UpdateStatus()
222 {
223 if (!sock->IsConnected()) {
224 SetStatusText("Not connected", 0);
225 SetStatusText("", 1);
226 } else {
227 wxIPV4address addr;
228 wxChar s[100];
229
230 sock->GetPeer(addr);
231 wxSprintf(s, _T("Connected to %s"), WXSTRINGCAST addr.Hostname());
232 SetStatusText(s, 0);
233 wxSprintf(s, _T("Service: %d"), addr.Service());
234 SetStatusText(s, 1);
235 }
236 }
237
238 void MyFrame::OnExecTest1(wxCommandEvent& WXUNUSED(evt))
239 {
240 if (!sock->IsConnected())
241 return;
242
243 wxDialog *dlgbox = new wxDialog(this, -1, "Test 1", wxDefaultPosition, wxSize(414, 280));
244 wxTextCtrl *text_win = new wxTextCtrl(dlgbox, -1, "",
245 wxPoint(0, 0), wxSize(400, 200),
246 wxTE_MULTILINE);
247 (void)new wxButton(dlgbox, ID_TEST_CLOSE, "Close",
248 wxPoint(100, 210), wxSize(100, -1));
249 wxChar *buf, *buf2;
250
251 dlgbox->Layout();
252 dlgbox->Show(TRUE);
253
254 text_win->WriteText("Initializing test 1 ...\n");
255
256 wxYield();
257
258 /* Init */
259 buf = copystring(_T("Hi ! Hi ! Hi !\n"));
260 buf2 = new wxChar[wxStrlen(buf)+1];
261 char c = 0xbe;
262 sock->Write(&c, 1);
263
264 /* No 1 */
265 text_win->WriteText("Sending some byte to the server ...");
266 wxYield();
267 sock->Write((char *)buf, wxStrlen(buf)+1);
268 text_win->WriteText("done\n");
269 wxYield();
270 text_win->WriteText("Receiving some byte from the server ...");
271 wxYield();
272 sock->Read((char *)buf2, wxStrlen(buf)+1);
273 text_win->WriteText("done\n");
274 wxYield();
275
276 text_win->WriteText("Comparing the two buffers ...");
277 if (memcmp(buf, buf2, wxStrlen(buf)+1) != 0) {
278 text_win->WriteText("Fail\n");
279 sock->Close();
280 UpdateStatus();
281 } else
282 text_win->WriteText("done\nTest 1A passed !\n");
283
284 /* No 2 */
285 sock->SetEventHandler(*this, SKDEMO_SCK);
286 sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
287 sock->Notify(TRUE);
288
289 text_win->WriteText("Test 1B: sending bytes to the server\n");
290 wxYield();
291 sock->Write((char *)buf, wxStrlen(buf)+1);
292 text_win->WriteText("Waiting for incoming bytes (timeout = 2 sec) ...");
293 wxYield();
294
295 m_good = 2;
296
297 MyFrameSocketTimer timer;
298
299 timer.m_var = &m_good;
300 timer.Start(2000, TRUE);
301
302 while (m_good == 2)
303 wxYield();
304
305 if (!m_good) {
306 text_win->WriteText("Timeout ! Failed.\n");
307 sock->Close();
308 UpdateStatus();
309 } else
310 text_win->WriteText("Success.");
311
312 sock->Read((char *)buf2, wxStrlen(buf)+1);
313
314 dlgbox->Layout();
315 dlgbox->ShowModal();
316
317 delete [] buf;
318 delete [] buf2;
319 delete text_win;
320 delete dlgbox;
321 }
322
323
324 void MyFrame::Download(wxInputStream *input)
325 {
326 wxProgressDialog progress("Downloading ...", "0% downloaded");
327 wxFileOutputStream f_out("test.url");
328 size_t downloaded;
329 int BUFSIZE, bytes_read;
330 size_t file_size;
331 wxString message;
332 int percents;
333
334 char *buf;
335
336 if (input->GetSize() == (size_t)-1) {
337 file_size = (size_t)-1;
338 bytes_read = BUFSIZE = 10240;
339 } else {
340 file_size = input->GetSize();
341 if (file_size > 10240)
342 bytes_read = BUFSIZE = file_size / 1024;
343 else
344 bytes_read = BUFSIZE = 1024;
345 }
346 buf = new char[BUFSIZE];
347
348 downloaded = 0;
349 bytes_read = BUFSIZE;
350 while (downloaded < file_size && bytes_read != 0) {
351 bytes_read = input->Read(buf, BUFSIZE).LastRead();
352 f_out.Write(buf, bytes_read);
353 downloaded += bytes_read;
354
355 percents = downloaded * 100 / file_size;
356
357 message = _T("");
358 message << percents << _T("% downloaded");
359 progress.Update(percents, message);
360 }
361
362 delete[] buf;
363 }
364
365 void MyFrame::OnExecUrlTest(wxCommandEvent& WXUNUSED(evt))
366 {
367 wxString urlname = wxGetTextFromUser("Enter an URL to get",
368 "URL:", "http://localhost");
369
370 wxURL url(urlname);
371 wxInputStream *datas = url.GetInputStream();
372
373 if (!datas) {
374 wxString error;
375 error.Printf(_T("Error in getting data from the URL. (error = %d)"), url.GetError());
376 wxMessageBox(error, "Alert !");
377 } else {
378 Download(datas);
379
380 delete datas;
381 }
382 }