]>
Commit | Line | Data |
---|---|---|
f4ada568 GL |
1 | /* |
2 | * File: client.cpp | |
3 | * Purpose: wxSocket: client demo | |
e2a6f233 | 4 | * Author: LAVAUX Guilhem |
f4ada568 | 5 | * Created: June 1997 |
062c4861 | 6 | * CVS ID: $Id$ |
e2a6f233 | 7 | * Copyright: (c) 1997, LAVAUX Guilhem |
f4ada568 | 8 | */ |
e2a6f233 | 9 | |
f4ada568 GL |
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 | |
e2a6f233 | 25 | |
a737331d | 26 | #include "wx/wfstream.h" |
f4ada568 GL |
27 | #include "wx/socket.h" |
28 | #include "wx/url.h" | |
29 | #include "wx/protocol/http.h" | |
6b3eb77a | 30 | #include "wx/thread.h" |
a324a7bc | 31 | #include "wx/progdlg.h" |
f4ada568 | 32 | |
e2a6f233 JS |
33 | #if defined(__WXMOTIF__) || defined(__WXGTK__) |
34 | #include "mondrian.xpm" | |
35 | #endif | |
36 | ||
f4ada568 GL |
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; | |
765e386b | 51 | int m_good; |
f4ada568 GL |
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); | |
765e386b | 61 | void OnSocketEvent(wxSocketEvent& evt); |
f4ada568 GL |
62 | void UpdateStatus(); |
63 | ||
a324a7bc GL |
64 | void Download(wxInputStream *input); |
65 | ||
f4ada568 GL |
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 | ||
a324a7bc | 80 | void OnNotify(GSocketEventFlags WXUNUSED(flags)) { frame->UpdateStatus(); } |
f4ada568 GL |
81 | }; |
82 | ||
83 | // ID for the menu quit command | |
db131261 RR |
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; | |
765e386b | 91 | const int SKDEMO_SCK = 108; |
f4ada568 GL |
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 | |
e2a6f233 | 104 | frame->SetIcon(wxICON(mondrian)); |
f4ada568 GL |
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"); | |
f4ada568 GL |
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 | |
e2a6f233 | 127 | (void)new wxPanel(frame, -1, wxPoint(0, 0), wxSize(300, 100)); |
f4ada568 GL |
128 | |
129 | // Show the frame | |
130 | frame->Show(TRUE); | |
131 | ||
132 | // Return the main frame window | |
27529614 | 133 | return TRUE; |
f4ada568 GL |
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 | { | |
f4ada568 | 143 | sock = new MyClient(); |
9111db68 | 144 | sock->SetFlags((wxSocketBase::wxSockFlags) (wxSocketBase::WAITALL | wxSocketBase::SPEED)); |
f4ada568 | 145 | sock->frame = this; |
2618484f | 146 | sock->SetNotify(wxSOCKET_LOST_FLAG); |
f4ada568 GL |
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); | |
11235b74 GRG |
172 | sock->Connect(addr, FALSE); |
173 | sock->WaitOnConnect(10); | |
a324a7bc | 174 | sock->SetFlags(wxSocketBase::NONE); |
f4ada568 GL |
175 | if (!sock->IsConnected()) |
176 | wxMessageBox("Can't connect to the specified host", "Alert !"); | |
177 | ||
178 | UpdateStatus(); | |
179 | } | |
180 | ||
181 | void MyFrame::OnExecCloseConnection(wxCommandEvent& WXUNUSED(evt)) | |
182 | { | |
a324a7bc | 183 | sock->Close(); |
f4ada568 GL |
184 | UpdateStatus(); |
185 | } | |
186 | ||
187 | BEGIN_EVENT_TABLE(MyFrame, wxFrame) | |
188 | EVT_BUTTON(ID_TEST_CLOSE, MyFrame::OnCloseTest) | |
189 | EVT_MENU(SKDEMO_TEST1, MyFrame::OnExecTest1) | |
190 | EVT_MENU(SKDEMO_TEST3, MyFrame::OnExecUrlTest) | |
191 | EVT_MENU(SKDEMO_QUIT, MyFrame::OnQuitApp) | |
192 | EVT_MENU(SKDEMO_CONNECT, MyFrame::OnExecOpenConnection) | |
193 | EVT_MENU(SKDEMO_CLOSE, MyFrame::OnExecCloseConnection) | |
765e386b | 194 | EVT_SOCKET(SKDEMO_SCK, MyFrame::OnSocketEvent) |
f4ada568 GL |
195 | END_EVENT_TABLE() |
196 | ||
765e386b GL |
197 | class MyFrameSocketTimer: public wxTimer { |
198 | public: | |
199 | void Notify() { | |
200 | *m_var = 0; | |
201 | } | |
202 | ||
203 | int *m_var; | |
204 | }; | |
205 | ||
206 | void MyFrame::OnSocketEvent(wxSocketEvent& evt) | |
207 | { | |
208 | m_good = 1; | |
209 | } | |
210 | ||
f4ada568 GL |
211 | void MyFrame::OnCloseTest(wxCommandEvent& evt) |
212 | { | |
213 | wxButton *button = (wxButton *)evt.GetEventObject(); | |
214 | wxDialog *dlg = (wxDialog *)button->GetParent(); | |
215 | ||
216 | dlg->EndModal(0); | |
217 | } | |
218 | ||
219 | void MyFrame::UpdateStatus() | |
220 | { | |
221 | if (!sock->IsConnected()) { | |
222 | SetStatusText("Not connected", 0); | |
223 | SetStatusText("", 1); | |
224 | } else { | |
225 | wxIPV4address addr; | |
a737331d | 226 | wxChar s[100]; |
f4ada568 GL |
227 | |
228 | sock->GetPeer(addr); | |
a737331d | 229 | wxSprintf(s, _T("Connected to %s"), WXSTRINGCAST addr.Hostname()); |
f4ada568 | 230 | SetStatusText(s, 0); |
a737331d | 231 | wxSprintf(s, _T("Service: %d"), addr.Service()); |
f4ada568 GL |
232 | SetStatusText(s, 1); |
233 | } | |
234 | } | |
235 | ||
236 | void MyFrame::OnExecTest1(wxCommandEvent& WXUNUSED(evt)) | |
237 | { | |
238 | if (!sock->IsConnected()) | |
239 | return; | |
240 | ||
11235b74 | 241 | wxDialog *dlgbox = new wxDialog(this, -1, "Test 1", wxDefaultPosition, wxSize(414, 280)); |
f4ada568 GL |
242 | wxTextCtrl *text_win = new wxTextCtrl(dlgbox, -1, "", |
243 | wxPoint(0, 0), wxSize(400, 200), | |
244 | wxTE_MULTILINE); | |
245 | (void)new wxButton(dlgbox, ID_TEST_CLOSE, "Close", | |
db131261 | 246 | wxPoint(100, 210), wxSize(100, -1)); |
a737331d | 247 | wxChar *buf, *buf2; |
f4ada568 GL |
248 | |
249 | dlgbox->Layout(); | |
250 | dlgbox->Show(TRUE); | |
251 | ||
252 | text_win->WriteText("Initializing test 1 ...\n"); | |
253 | ||
db131261 RR |
254 | wxYield(); |
255 | ||
f4ada568 | 256 | /* Init */ |
a737331d GL |
257 | buf = copystring(_T("Hi ! Hi ! Hi !\n")); |
258 | buf2 = new wxChar[wxStrlen(buf)+1]; | |
f4ada568 | 259 | char c = 0xbe; |
a737331d | 260 | sock->Write(&c, 1); |
f4ada568 GL |
261 | |
262 | /* No 1 */ | |
263 | text_win->WriteText("Sending some byte to the server ..."); | |
a737331d GL |
264 | wxYield(); |
265 | sock->Write((char *)buf, wxStrlen(buf)+1); | |
f4ada568 | 266 | text_win->WriteText("done\n"); |
a737331d | 267 | wxYield(); |
f4ada568 | 268 | text_win->WriteText("Receiving some byte from the server ..."); |
a737331d GL |
269 | wxYield(); |
270 | sock->Read((char *)buf2, wxStrlen(buf)+1); | |
f4ada568 | 271 | text_win->WriteText("done\n"); |
a737331d | 272 | wxYield(); |
f4ada568 GL |
273 | |
274 | text_win->WriteText("Comparing the two buffers ..."); | |
a737331d | 275 | if (memcmp(buf, buf2, wxStrlen(buf)+1) != 0) { |
f4ada568 GL |
276 | text_win->WriteText("Fail\n"); |
277 | sock->Close(); | |
278 | UpdateStatus(); | |
279 | } else | |
765e386b GL |
280 | text_win->WriteText("done\nTest 1A passed !\n"); |
281 | ||
282 | /* No 2 */ | |
283 | sock->SetEventHandler(*this, SKDEMO_SCK); | |
2618484f | 284 | sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG); |
765e386b | 285 | sock->Notify(TRUE); |
765e386b | 286 | text_win->WriteText("Test 1B: sending bytes to the server\n"); |
83802b0b GRG |
287 | if (!sock->IsData()) |
288 | text_win->WriteText("No data to read yet (this is OK)\n"); | |
289 | ||
765e386b GL |
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) { | |
83802b0b | 306 | text_win->WriteText("timeout ! Failed.\n"); |
765e386b GL |
307 | sock->Close(); |
308 | UpdateStatus(); | |
309 | } else | |
83802b0b GRG |
310 | text_win->WriteText("event ! (no timeout).\n"); |
311 | ||
312 | if (sock->IsData()) | |
313 | text_win->WriteText("Data is available, as expected...\n"); | |
765e386b GL |
314 | |
315 | sock->Read((char *)buf2, wxStrlen(buf)+1); | |
f4ada568 | 316 | |
83802b0b GRG |
317 | text_win->WriteText("Success!\n"); |
318 | ||
f4ada568 GL |
319 | dlgbox->Layout(); |
320 | dlgbox->ShowModal(); | |
321 | ||
322 | delete [] buf; | |
323 | delete [] buf2; | |
324 | delete text_win; | |
325 | delete dlgbox; | |
326 | } | |
327 | ||
a324a7bc GL |
328 | |
329 | void MyFrame::Download(wxInputStream *input) | |
330 | { | |
331 | wxProgressDialog progress("Downloading ...", "0% downloaded"); | |
a324a7bc | 332 | wxFileOutputStream f_out("test.url"); |
a324a7bc | 333 | size_t downloaded; |
f61815af GL |
334 | int BUFSIZE, bytes_read; |
335 | size_t file_size; | |
a324a7bc GL |
336 | wxString message; |
337 | int percents; | |
338 | ||
339 | char *buf; | |
340 | ||
f61815af GL |
341 | if (input->GetSize() == (size_t)-1) { |
342 | file_size = (size_t)-1; | |
343 | bytes_read = BUFSIZE = 10240; | |
344 | } else { | |
345 | file_size = input->GetSize(); | |
346 | if (file_size > 10240) | |
347 | bytes_read = BUFSIZE = file_size / 1024; | |
348 | else | |
349 | bytes_read = BUFSIZE = 1024; | |
350 | } | |
a324a7bc GL |
351 | buf = new char[BUFSIZE]; |
352 | ||
353 | downloaded = 0; | |
354 | bytes_read = BUFSIZE; | |
355 | while (downloaded < file_size && bytes_read != 0) { | |
f61815af | 356 | bytes_read = input->Read(buf, BUFSIZE).LastRead(); |
a324a7bc GL |
357 | f_out.Write(buf, bytes_read); |
358 | downloaded += bytes_read; | |
359 | ||
360 | percents = downloaded * 100 / file_size; | |
361 | ||
362 | message = _T(""); | |
363 | message << percents << _T("% downloaded"); | |
364 | progress.Update(percents, message); | |
365 | } | |
366 | ||
367 | delete[] buf; | |
368 | } | |
369 | ||
f4ada568 GL |
370 | void MyFrame::OnExecUrlTest(wxCommandEvent& WXUNUSED(evt)) |
371 | { | |
856d2e52 GL |
372 | wxString urlname = wxGetTextFromUser("Enter an URL to get", |
373 | "URL:", "http://localhost"); | |
f4ada568 GL |
374 | |
375 | wxURL url(urlname); | |
376 | wxInputStream *datas = url.GetInputStream(); | |
377 | ||
062c4861 GL |
378 | if (!datas) { |
379 | wxString error; | |
380 | error.Printf(_T("Error in getting data from the URL. (error = %d)"), url.GetError()); | |
381 | wxMessageBox(error, "Alert !"); | |
382 | } else { | |
a324a7bc | 383 | Download(datas); |
a737331d | 384 | |
f4ada568 GL |
385 | delete datas; |
386 | } | |
387 | } |