]>
git.saurik.com Git - wxWidgets.git/blob - samples/sockets/server.cpp
28743adf9a1fe9e77298434726be93755797bb83
   1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Server 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 // -------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx/wx.h". 
  21 #include "wx/wxprec.h" 
  27 // for all others, include the necessary headers 
  32 #include "wx/socket.h" 
  34 // this example is currently written to use only IP or only IPv6 sockets, it 
  35 // should be extended to allow using either in the future 
  37     typedef wxIPV6address IPaddress
; 
  39     typedef wxIPV4address IPaddress
; 
  42 // -------------------------------------------------------------------------- 
  44 // -------------------------------------------------------------------------- 
  46 // the application icon 
  47 #include "mondrian.xpm" 
  49 // -------------------------------------------------------------------------- 
  51 // -------------------------------------------------------------------------- 
  53 // Define a new application type 
  54 class MyApp 
: public wxApp
 
  57   virtual bool OnInit(); 
  60 // Define a new frame type: this is going to be our main frame 
  61 class MyFrame 
: public wxFrame
 
  67   // event handlers (these functions should _not_ be virtual) 
  68   void OnQuit(wxCommandEvent
& event
); 
  69   void OnAbout(wxCommandEvent
& event
); 
  70   void OnServerEvent(wxSocketEvent
& event
); 
  71   void OnSocketEvent(wxSocketEvent
& event
); 
  73   void Test1(wxSocketBase 
*sock
); 
  74   void Test2(wxSocketBase 
*sock
); 
  75   void Test3(wxSocketBase 
*sock
); 
  77   // convenience functions 
  78   void UpdateStatusBar(); 
  81   wxSocketServer 
*m_server
; 
  88   // any class wishing to process wxWidgets events must use this macro 
  92 // simple helper class to log start and end of each test 
  96     TestLogger(const wxString
& name
) : m_name(name
) 
  98         wxLogMessage("=== %s begins ===", m_name
); 
 103         wxLogMessage("=== %s ends ===", m_name
); 
 107     const wxString m_name
; 
 110 // -------------------------------------------------------------------------- 
 112 // -------------------------------------------------------------------------- 
 114 // IDs for the controls and the menu commands 
 118   SERVER_QUIT 
= wxID_EXIT
, 
 119   SERVER_ABOUT 
= wxID_ABOUT
, 
 126 // -------------------------------------------------------------------------- 
 127 // event tables and other macros for wxWidgets 
 128 // -------------------------------------------------------------------------- 
 130 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
) 
 131   EVT_MENU(SERVER_QUIT
,  MyFrame::OnQuit
) 
 132   EVT_MENU(SERVER_ABOUT
, MyFrame::OnAbout
) 
 133   EVT_SOCKET(SERVER_ID
,  MyFrame::OnServerEvent
) 
 134   EVT_SOCKET(SOCKET_ID
,  MyFrame::OnSocketEvent
) 
 140 // ========================================================================== 
 142 // ========================================================================== 
 144 // -------------------------------------------------------------------------- 
 145 // the application class 
 146 // -------------------------------------------------------------------------- 
 150   if ( !wxApp::OnInit() ) 
 153   // Create the main application window 
 154   MyFrame 
*frame 
= new MyFrame(); 
 156   // Show it and tell the application that it's our main window 
 164 // -------------------------------------------------------------------------- 
 166 // -------------------------------------------------------------------------- 
 170 MyFrame::MyFrame() : wxFrame((wxFrame 
*)NULL
, wxID_ANY
, 
 171                              _("wxSocket demo: Server"), 
 172                              wxDefaultPosition
, wxSize(300, 200)) 
 174   // Give the frame an icon 
 175   SetIcon(wxICON(mondrian
)); 
 178   m_menuFile 
= new wxMenu(); 
 179   m_menuFile
->Append(SERVER_ABOUT
, _("&About...\tCtrl-A"), _("Show about dialog")); 
 180   m_menuFile
->AppendSeparator(); 
 181   m_menuFile
->Append(SERVER_QUIT
, _("E&xit\tAlt-X"), _("Quit server")); 
 183   // Append menus to the menubar 
 184   m_menuBar 
= new wxMenuBar(); 
 185   m_menuBar
->Append(m_menuFile
, _("&File")); 
 186   SetMenuBar(m_menuBar
); 
 191 #endif // wxUSE_STATUSBAR 
 193   // Make a textctrl for logging 
 194   m_text  
= new wxTextCtrl(this, wxID_ANY
, 
 195                            _("Welcome to wxSocket demo: Server\n"), 
 196                            wxDefaultPosition
, wxDefaultSize
, 
 197                            wxTE_MULTILINE 
| wxTE_READONLY
); 
 198   delete wxLog::SetActiveTarget(new wxLogTextCtrl(m_text
)); 
 200   // Create the address - defaults to localhost:0 initially 
 204   wxLogMessage("Creating server at %s:%u", addr
.IPAddress(), addr
.Service()); 
 207   m_server 
= new wxSocketServer(addr
); 
 209   // We use Ok() here to see if the server is really listening 
 210   if (! m_server
->Ok()) 
 212     wxLogMessage("Could not listen at the specified port !"); 
 217   if ( !m_server
->GetLocal(addrReal
) ) 
 218     wxLogMessage("ERROR: couldn't get the address we bound to"); 
 220     wxLogMessage("Server listening at %s:%u", 
 221                  addrReal
.IPAddress(), addrReal
.Service()); 
 223   // Setup the event handler and subscribe to connection events 
 224   m_server
->SetEventHandler(*this, SERVER_ID
); 
 225   m_server
->SetNotify(wxSOCKET_CONNECTION_FLAG
); 
 226   m_server
->Notify(true); 
 235   // No delayed deletion here, as the frame is dying anyway 
 241 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
)) 
 243   // true is to force the frame to close 
 247 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
)) 
 249   wxMessageBox(_("wxSocket demo: Server\n(c) 1999 Guillermo Rodriguez Garcia\n"), 
 251                wxOK 
| wxICON_INFORMATION
, this); 
 254 void MyFrame::Test1(wxSocketBase 
*sock
) 
 256   TestLogger 
logtest("Test 1"); 
 258   // Receive data from socket and send it back. We will first 
 259   // get a byte with the buffer size, so we can specify the 
 260   // exact size and use the wxSOCKET_WAITALL flag. Also, we 
 261   // disabled input events so we won't have unwanted reentrance. 
 262   // This way we can avoid the infamous wxSOCKET_BLOCK flag. 
 264   sock
->SetFlags(wxSOCKET_WAITALL
); 
 269   wxCharBuffer 
buf(len
); 
 272   sock
->Read(buf
.data(), len
); 
 273   wxLogMessage("Got the data, sending it back"); 
 276   sock
->Write(buf
, len
); 
 279 void MyFrame::Test2(wxSocketBase 
*sock
) 
 283   TestLogger 
logtest("Test 2"); 
 285   // We don't need to set flags because ReadMsg and WriteMsg 
 286   // are not affected by them anyway. 
 289   wxUint32 len 
= sock
->ReadMsg(buf
, sizeof(buf
)).LastCount(); 
 292       wxLogError("Failed to read message."); 
 296   wxLogMessage("Got \"%s\" from client.", wxString::FromUTF8(buf
, len
)); 
 297   wxLogMessage("Sending the data back"); 
 300   sock
->WriteMsg(buf
, len
); 
 303 void MyFrame::Test3(wxSocketBase 
*sock
) 
 305   TestLogger 
logtest("Test 3"); 
 307   // This test is similar to the first one, but the len is 
 308   // expressed in kbytes - this tests large data transfers. 
 310   sock
->SetFlags(wxSOCKET_WAITALL
); 
 315   wxCharBuffer 
buf(len
*1024); 
 318   sock
->Read(buf
.data(), len 
* 1024); 
 319   wxLogMessage("Got the data, sending it back"); 
 322   sock
->Write(buf
, len 
* 1024); 
 325 void MyFrame::OnServerEvent(wxSocketEvent
& event
) 
 327   wxString s 
= _("OnServerEvent: "); 
 330   switch(event
.GetSocketEvent()) 
 332     case wxSOCKET_CONNECTION 
: s
.Append(_("wxSOCKET_CONNECTION\n")); break; 
 333     default                  : s
.Append(_("Unexpected event !\n")); break; 
 336   m_text
->AppendText(s
); 
 338   // Accept new connection if there is one in the pending 
 339   // connections queue, else exit. We use Accept(false) for 
 340   // non-blocking accept (although if we got here, there 
 341   // should ALWAYS be a pending connection). 
 343   sock 
= m_server
->Accept(false); 
 348     if ( !sock
->GetPeer(addr
) ) 
 349       wxLogMessage("New connection from unknown client accepted."); 
 351       wxLogMessage("New client connection from %s:%u accepted", 
 352                    addr
.IPAddress(), addr
.Service()); 
 356     wxLogMessage("Error: couldn't accept a new connection"); 
 360   sock
->SetEventHandler(*this, SOCKET_ID
); 
 361   sock
->SetNotify(wxSOCKET_INPUT_FLAG 
| wxSOCKET_LOST_FLAG
); 
 368 void MyFrame::OnSocketEvent(wxSocketEvent
& event
) 
 370   wxString s 
= _("OnSocketEvent: "); 
 371   wxSocketBase 
*sock 
= event
.GetSocket(); 
 373   // First, print a message 
 374   switch(event
.GetSocketEvent()) 
 376     case wxSOCKET_INPUT 
: s
.Append(_("wxSOCKET_INPUT\n")); break; 
 377     case wxSOCKET_LOST  
: s
.Append(_("wxSOCKET_LOST\n")); break; 
 378     default             : s
.Append(_("Unexpected event !\n")); break; 
 381   m_text
->AppendText(s
); 
 383   // Now we process the event 
 384   switch(event
.GetSocketEvent()) 
 388       // We disable input events, so that the test doesn't trigger 
 389       // wxSocketEvent again. 
 390       sock
->SetNotify(wxSOCKET_LOST_FLAG
); 
 392       // Which test are we going to run? 
 398         case 0xBE: Test1(sock
); break; 
 399         case 0xCE: Test2(sock
); break; 
 400         case 0xDE: Test3(sock
); break; 
 402           wxLogMessage("Unknown test id received from client"); 
 405       // Enable input events again. 
 406       sock
->SetNotify(wxSOCKET_LOST_FLAG 
| wxSOCKET_INPUT_FLAG
); 
 413       // Destroy() should be used instead of delete wherever possible, 
 414       // due to the fact that wxSocket uses 'delayed events' (see the 
 415       // documentation for wxPostEvent) and we don't want an event to 
 416       // arrive to the event handler (the frame, here) after the socket 
 417       // has been deleted. Also, we might be doing some other thing with 
 418       // the socket at the same time; for example, we might be in the 
 419       // middle of a test or something. Destroy() takes care of all 
 422       wxLogMessage("Deleting socket."); 
 432 // convenience functions 
 434 void MyFrame::UpdateStatusBar() 
 438   s
.Printf(_("%d clients connected"), m_numClients
); 
 440 #endif // wxUSE_STATUSBAR