home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / samples / sockets / client.cpp < prev    next >
C/C++ Source or Header  |  2002-11-14  |  20KB  |  632 lines

  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: client.cpp,v 1.21.2.1 2002/11/11 19:07:23 RR Exp $
  8. // Copyright:   (c) 1999 Guillermo Rodriguez Garcia
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ==========================================================================
  13. // declarations
  14. // ==========================================================================
  15.  
  16. // --------------------------------------------------------------------------
  17. // headers
  18. // --------------------------------------------------------------------------
  19.  
  20. #if defined(__GNUG__) && !defined(__APPLE__)
  21. #  pragma implementation "client.cpp"
  22. #  pragma interface "client.cpp"
  23. #endif
  24.  
  25. // For compilers that support precompilation, includes "wx/wx.h".
  26. #include "wx/wxprec.h"
  27.  
  28. #ifdef __BORLANDC__
  29. #  pragma hdrstop
  30. #endif
  31.  
  32. // for all others, include the necessary headers 
  33. #ifndef WX_PRECOMP
  34. #  include "wx/wx.h"
  35. #endif
  36.  
  37. #include "wx/socket.h"
  38. #include "wx/url.h"
  39. #include "wx/wfstream.h"
  40.  
  41. // --------------------------------------------------------------------------
  42. // resources
  43. // --------------------------------------------------------------------------
  44.  
  45. // the application icon
  46. #if defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__) || defined(__WXMAC__)
  47. #  include "mondrian.xpm"
  48. #endif
  49.  
  50. // --------------------------------------------------------------------------
  51. // classes
  52. // --------------------------------------------------------------------------
  53.  
  54. // Define a new application type
  55. class MyApp : public wxApp
  56. {
  57. public:
  58.   virtual bool OnInit();
  59. };
  60.  
  61. // Define a new frame type: this is going to be our main frame
  62. class MyFrame : public wxFrame
  63. {
  64. public:
  65.   MyFrame();
  66.   ~MyFrame();
  67.  
  68.   // event handlers for File menu
  69.   void OnQuit(wxCommandEvent& event);
  70.   void OnAbout(wxCommandEvent& event);
  71.  
  72.   // event handlers for Socket menu
  73.   void OnOpenConnection(wxCommandEvent& event);
  74.   void OnTest1(wxCommandEvent& event);
  75.   void OnTest2(wxCommandEvent& event);
  76.   void OnTest3(wxCommandEvent& event);
  77.   void OnCloseConnection(wxCommandEvent& event);
  78.  
  79.   // event handlers for Protocols menu
  80.   void OnTestURL(wxCommandEvent& event);
  81.  
  82.   // event handlers for DatagramSocket menu (stub)
  83.   void OnDatagram(wxCommandEvent& event);
  84.  
  85.   // socket event handler
  86.   void OnSocketEvent(wxSocketEvent& event);
  87.  
  88.   // convenience functions
  89.   void UpdateStatusBar();
  90.  
  91. private:
  92.   wxSocketClient *m_sock;
  93.   wxTextCtrl     *m_text;
  94.   wxMenu         *m_menuFile;
  95.   wxMenu         *m_menuSocket;
  96.   wxMenu         *m_menuDatagramSocket;
  97.   wxMenu         *m_menuProtocols;
  98.   wxMenuBar      *m_menuBar;
  99.   bool            m_busy;
  100.  
  101.   // any class wishing to process wxWindows events must use this macro
  102.   DECLARE_EVENT_TABLE()
  103. };
  104.  
  105. // --------------------------------------------------------------------------
  106. // constants
  107. // --------------------------------------------------------------------------
  108.  
  109. // IDs for the controls and the menu commands
  110. enum
  111. {
  112.   // menu items
  113.   CLIENT_QUIT = 1000,
  114.   CLIENT_ABOUT,
  115.   CLIENT_OPEN,
  116.   CLIENT_TEST1,
  117.   CLIENT_TEST2,
  118.   CLIENT_TEST3,
  119.   CLIENT_CLOSE,
  120.   CLIENT_TESTURL,
  121.   CLIENT_DGRAM,
  122.  
  123.   // id for socket
  124.   SOCKET_ID
  125. };
  126.  
  127. // --------------------------------------------------------------------------
  128. // event tables and other macros for wxWindows
  129. // --------------------------------------------------------------------------
  130.  
  131. BEGIN_EVENT_TABLE(MyFrame, wxFrame)
  132.   EVT_MENU(CLIENT_QUIT,     MyFrame::OnQuit)
  133.   EVT_MENU(CLIENT_ABOUT,    MyFrame::OnAbout)
  134.   EVT_MENU(CLIENT_OPEN,     MyFrame::OnOpenConnection)
  135.   EVT_MENU(CLIENT_TEST1,    MyFrame::OnTest1)
  136.   EVT_MENU(CLIENT_TEST2,    MyFrame::OnTest2)
  137.   EVT_MENU(CLIENT_TEST3,    MyFrame::OnTest3)
  138.   EVT_MENU(CLIENT_CLOSE,    MyFrame::OnCloseConnection)
  139.   EVT_MENU(CLIENT_DGRAM,    MyFrame::OnDatagram)
  140.   EVT_MENU(CLIENT_TESTURL,  MyFrame::OnTestURL)
  141.   EVT_SOCKET(SOCKET_ID,     MyFrame::OnSocketEvent)
  142. END_EVENT_TABLE()
  143.  
  144. IMPLEMENT_APP(MyApp)
  145.  
  146. // ==========================================================================
  147. // implementation
  148. // ==========================================================================
  149.  
  150. // --------------------------------------------------------------------------
  151. // the application class
  152. // --------------------------------------------------------------------------
  153.  
  154. bool MyApp::OnInit()
  155. {
  156.   // Create the main application window
  157.   MyFrame *frame = new MyFrame();
  158.  
  159.   // Show it and tell the application that it's our main window
  160.   frame->Show(TRUE);
  161.   SetTopWindow(frame);
  162.  
  163.   // success
  164.   return TRUE;
  165. }
  166.  
  167. // --------------------------------------------------------------------------
  168. // main frame
  169. // --------------------------------------------------------------------------
  170.  
  171. // frame constructor
  172. MyFrame::MyFrame() : wxFrame((wxFrame *)NULL, -1,
  173.                              _("wxSocket demo: Client"),
  174.                              wxDefaultPosition, wxSize(300, 200))
  175. {
  176.   // Give the frame an icon
  177.   SetIcon(wxICON(mondrian));
  178.  
  179.   // Make menus
  180.   m_menuFile = new wxMenu();
  181.   m_menuFile->Append(CLIENT_ABOUT, _("&About...\tCtrl-A"), _("Show about dialog"));
  182.   m_menuFile->AppendSeparator();
  183.   m_menuFile->Append(CLIENT_QUIT, _("E&xit\tAlt-X"), _("Quit client"));
  184.  
  185.   m_menuSocket = new wxMenu();
  186.   m_menuSocket->Append(CLIENT_OPEN, _("&Open session"), _("Connect to server"));
  187.   m_menuSocket->AppendSeparator();
  188.   m_menuSocket->Append(CLIENT_TEST1, _("Test &1"), _("Test basic functionality"));
  189.   m_menuSocket->Append(CLIENT_TEST2, _("Test &2"), _("Test ReadMsg and WriteMsg"));
  190.   m_menuSocket->Append(CLIENT_TEST3, _("Test &3"), _("Test large data transfer"));
  191.   m_menuSocket->AppendSeparator();
  192.   m_menuSocket->Append(CLIENT_CLOSE, _("&Close session"), _("Close connection"));
  193.  
  194.   m_menuDatagramSocket = new wxMenu();
  195.   m_menuDatagramSocket->Append(CLIENT_DGRAM, _("Send Datagram"), _("Test UDP sockets"));
  196.  
  197.   m_menuProtocols = new wxMenu();
  198.   m_menuProtocols->Append(CLIENT_TESTURL, _("Test URL"), _("Get data from the specified URL"));
  199.  
  200.   // Append menus to the menubar
  201.   m_menuBar = new wxMenuBar();
  202.   m_menuBar->Append(m_menuFile, _("&File"));
  203.   m_menuBar->Append(m_menuSocket, _("&SocketClient"));
  204.   m_menuBar->Append(m_menuDatagramSocket, _("&DatagramSocket"));
  205.   m_menuBar->Append(m_menuProtocols, _("&Protocols"));
  206.   SetMenuBar(m_menuBar);
  207.  
  208.   // Status bar
  209.   CreateStatusBar(2);
  210.  
  211.   // Make a textctrl for logging
  212.   m_text  = new wxTextCtrl(this, -1,
  213.                            _("Welcome to wxSocket demo: Client\nClient ready\n"),
  214.                            wxDefaultPosition, wxDefaultSize,
  215.                            wxTE_MULTILINE | wxTE_READONLY);
  216.  
  217.   // Create the socket
  218.   m_sock = new wxSocketClient();
  219.  
  220.   // Setup the event handler and subscribe to most events
  221.   m_sock->SetEventHandler(*this, SOCKET_ID);
  222.   m_sock->SetNotify(wxSOCKET_CONNECTION_FLAG |
  223.                     wxSOCKET_INPUT_FLAG |
  224.                     wxSOCKET_LOST_FLAG);
  225.   m_sock->Notify(TRUE);
  226.  
  227.   m_busy = FALSE;
  228.   UpdateStatusBar();
  229. }
  230.  
  231. MyFrame::~MyFrame()
  232. {
  233.   // No delayed deletion here, as the frame is dying anyway
  234.   delete m_sock;
  235. }
  236.  
  237. // event handlers
  238.  
  239. void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
  240. {
  241.   // TRUE is to force the frame to close
  242.   Close(TRUE);
  243. }
  244.  
  245. void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
  246. {
  247.   wxMessageBox(_("wxSocket demo: Client\n(c) 1999 Guillermo Rodriguez Garcia\n"),
  248.                _("About Client"),
  249.                wxOK | wxICON_INFORMATION, this);
  250. }
  251.  
  252. void MyFrame::OnOpenConnection(wxCommandEvent& WXUNUSED(event))
  253. {
  254.   wxIPV4address addr;
  255.  
  256.   m_menuSocket->Enable(CLIENT_OPEN, FALSE);
  257.   m_menuSocket->Enable(CLIENT_CLOSE, FALSE);
  258.  
  259.   // Ask user for server address
  260.   wxString hostname = wxGetTextFromUser(
  261.     _("Enter the address of the wxSocket demo server:"),
  262.     _("Connect ..."),
  263.     _("localhost"));
  264.  
  265.   addr.Hostname(hostname);
  266.   addr.Service(3000);
  267.  
  268.   // Mini-tutorial for Connect() :-)
  269.   // ---------------------------
  270.   //
  271.   // There are two ways to use Connect(): blocking and non-blocking,
  272.   // depending on the value passed as the 'wait' (2nd) parameter.
  273.   //
  274.   // Connect(addr, TRUE) will wait until the connection completes,
  275.   // returning TRUE on success and FALSE on failure. This call blocks
  276.   // the GUI (this might be changed in future releases to honour the
  277.   // wxSOCKET_BLOCK flag).
  278.   //
  279.   // Connect(addr, FALSE) will issue a nonblocking connection request
  280.   // and return immediately. If the return value is TRUE, then the
  281.   // connection has been already succesfully established. If it is
  282.   // FALSE, you must wait for the request to complete, either with
  283.   // WaitOnConnect() or by watching wxSOCKET_CONNECTION / LOST
  284.   // events (please read the documentation).
  285.   //
  286.   // WaitOnConnect() itself never blocks the GUI (this might change
  287.   // in the future to honour the wxSOCKET_BLOCK flag). This call will
  288.   // return FALSE on timeout, or TRUE if the connection request
  289.   // completes, which in turn might mean:
  290.   //
  291.   //   a) That the connection was successfully established
  292.   //   b) That the connection request failed (for example, because
  293.   //      it was refused by the peer.
  294.   //
  295.   // Use IsConnected() to distinguish between these two.
  296.   //
  297.   // So, in a brief, you should do one of the following things:
  298.   //
  299.   // For blocking Connect:
  300.   //
  301.   //   bool success = client->Connect(addr, TRUE);
  302.   //
  303.   // For nonblocking Connect:
  304.   //
  305.   //   client->Connect(addr, FALSE);
  306.   //
  307.   //   bool waitmore = TRUE;
  308.   //   while (! client->WaitOnConnect(seconds, millis) && waitmore )
  309.   //   {
  310.   //     // possibly give some feedback to the user,
  311.   //     // update waitmore if needed.
  312.   //   }
  313.   //   bool success = client->IsConnected();
  314.   // 
  315.   // And that's all :-)
  316.  
  317.   m_text->AppendText(_("\nTrying to connect (timeout = 10 sec) ...\n"));
  318.   m_sock->Connect(addr, FALSE);
  319.   m_sock->WaitOnConnect(10);
  320.  
  321.   if (m_sock->IsConnected())
  322.     m_text->AppendText(_("Succeeded ! Connection established\n"));
  323.   else
  324.   {
  325.     m_sock->Close();
  326.     m_text->AppendText(_("Failed ! Unable to connect\n"));
  327.     wxMessageBox(_("Can't connect to the specified host"), _("Alert !"));
  328.   }
  329.   
  330.   UpdateStatusBar();
  331. }
  332.  
  333. void MyFrame::OnTest1(wxCommandEvent& WXUNUSED(event))
  334. {
  335.   const wxChar *buf1;
  336.   wxChar       *buf2;
  337.   unsigned char len;
  338.  
  339.   // Disable socket menu entries (exception: Close Session)
  340.   m_busy = TRUE;
  341.   UpdateStatusBar();
  342.  
  343.   m_text->AppendText(_("\n=== Test 1 begins ===\n"));
  344.  
  345.   // Tell the server which test we are running
  346.   unsigned char c = 0xBE;
  347.   m_sock->Write(&c, 1);
  348.  
  349.   // Send some data and read it back. We know the size of the
  350.   // buffer, so we can specify the exact number of bytes to be
  351.   // sent or received and use the wxSOCKET_WAITALL flag. Also,
  352.   // we have disabled menu entries which could interfere with
  353.   // the test, so we can safely avoid the wxSOCKET_BLOCK flag.
  354.   //
  355.   // First we send a byte with the length of the string, then
  356.   // we send the string itself (do NOT try to send any integral
  357.   // value larger than a byte "as is" across the network, or
  358.   // you might be in trouble! Ever heard about big and little
  359.   // endian computers?)
  360.  
  361.   m_sock->SetFlags(wxSOCKET_WAITALL);
  362.  
  363.   buf1 = _("Test string (less than 256 chars!)");
  364.   len  = (wxStrlen(buf1) + 1) * sizeof(wxChar);
  365.   buf2 = new wxChar[wxStrlen(buf1) + 1];
  366.  
  367.   m_text->AppendText(_("Sending a test buffer to the server ..."));
  368.   m_sock->Write(&len, 1);
  369.   m_sock->Write(buf1, len);
  370.   m_text->AppendText(m_sock->Error() ? _("failed !\n") : _("done\n"));
  371.  
  372.   m_text->AppendText(_("Receiving the buffer back from server ..."));
  373.   m_sock->Read(buf2, len);
  374.   m_text->AppendText(m_sock->Error() ? _("failed !\n") : _("done\n"));
  375.  
  376.   m_text->AppendText(_("Comparing the two buffers ..."));
  377.   if (memcmp(buf1, buf2, len) != 0)
  378.   {
  379.     m_text->AppendText(_("failed!\n"));
  380.     m_text->AppendText(_("Test 1 failed !\n"));
  381.   }
  382.   else
  383.   {
  384.     m_text->AppendText(_("done\n"));
  385.     m_text->AppendText(_("Test 1 passed !\n"));
  386.   }
  387.   m_text->AppendText(_("=== Test 1 ends ===\n"));
  388.  
  389.   delete[] buf2;
  390.   m_busy = FALSE;
  391.   UpdateStatusBar();
  392. }
  393.  
  394. void MyFrame::OnTest2(wxCommandEvent& WXUNUSED(event))
  395. {
  396.   const wxChar *msg1;
  397.   wxChar *msg2;
  398.   size_t len;
  399.  
  400.   // Disable socket menu entries (exception: Close Session)
  401.   m_busy = TRUE;
  402.   UpdateStatusBar();
  403.  
  404.   m_text->AppendText(_("\n=== Test 2 begins ===\n"));
  405.  
  406.   // Tell the server which test we are running
  407.   unsigned char c = 0xCE;
  408.   m_sock->Write(&c, 1);
  409.  
  410.   // Here we use ReadMsg and WriteMsg to send messages with
  411.   // a header with size information. Also, the reception is
  412.   // event triggered, so we test input events as well.
  413.   //
  414.   // We need to set no flags here (ReadMsg and WriteMsg are
  415.   // not affected by flags)
  416.  
  417.   m_sock->SetFlags(wxSOCKET_WAITALL);
  418.  
  419.   wxString s = wxGetTextFromUser(
  420.     _("Enter an arbitrary string to send to the server:"),
  421.     _("Test 2 ..."),
  422.     _("Yes I like wxWindows!"));
  423.  
  424.   msg1 = s.c_str();
  425.   len  = (wxStrlen(msg1) + 1) * sizeof(wxChar);
  426.   msg2 = new wxChar[wxStrlen(msg1) + 1];
  427.  
  428.   m_text->AppendText(_("Sending the string with WriteMsg ..."));
  429.   m_sock->WriteMsg(msg1, len);
  430.   m_text->AppendText(m_sock->Error() ? _("failed !\n") : _("done\n"));
  431.   m_text->AppendText(_("Waiting for an event (timeout = 2 sec)\n"));
  432.  
  433.   // Wait until data available (will also return if the connection is lost)
  434.   m_sock->WaitForRead(2);
  435.  
  436.   if (m_sock->IsData())
  437.   {
  438.     m_text->AppendText(_("Reading the string back with ReadMsg ..."));
  439.     m_sock->ReadMsg(msg2, len);
  440.     m_text->AppendText(m_sock->Error() ? _("failed !\n") : _("done\n"));
  441.     m_text->AppendText(_("Comparing the two buffers ..."));
  442.     if (memcmp(msg1, msg2, len) != 0)
  443.     {
  444.       m_text->AppendText(_("failed!\n"));  
  445.       m_text->AppendText(_("Test 2 failed !\n"));
  446.     }
  447.     else
  448.     {
  449.       m_text->AppendText(_("done\n"));
  450.       m_text->AppendText(_("Test 2 passed !\n"));
  451.     }
  452.   }
  453.   else
  454.     m_text->AppendText(_("Timeout ! Test 2 failed.\n"));
  455.  
  456.   m_text->AppendText(_("=== Test 2 ends ===\n"));
  457.  
  458.   delete[] msg2;
  459.   m_busy = FALSE;
  460.   UpdateStatusBar();
  461. }
  462.  
  463. void MyFrame::OnTest3(wxCommandEvent& WXUNUSED(event))
  464. {
  465.   char *buf1;
  466.   char *buf2;
  467.   unsigned char len;
  468.  
  469.   // Disable socket menu entries (exception: Close Session)
  470.   m_busy = TRUE;
  471.   UpdateStatusBar();
  472.  
  473.   m_text->AppendText(_("\n=== Test 3 begins ===\n"));
  474.  
  475.   // Tell the server which test we are running
  476.   unsigned char c = 0xDE;
  477.   m_sock->Write(&c, 1);
  478.  
  479.   // This test also is similar to the first one but it sends a
  480.   // large buffer so that wxSocket is actually forced to split
  481.   // it into pieces and take care of sending everything before
  482.   // returning.
  483.  
  484.   m_sock->SetFlags(wxSOCKET_WAITALL);
  485.  
  486.   // Note that len is in kbytes here!
  487.   len  = 32;
  488.   buf1 = new char[len * 1024];
  489.   buf2 = new char[len * 1024];
  490.  
  491.   for (int i = 0; i < len * 1024; i ++)
  492.     buf1[i] = (char)(i % 256);
  493.  
  494.   m_text->AppendText(_("Sending a large buffer (32K) to the server ..."));
  495.   m_sock->Write(&len, 1);
  496.   m_sock->Write(buf1, len * 1024);
  497.   m_text->AppendText(m_sock->Error() ? _("failed !\n") : _("done\n"));
  498.  
  499.   m_text->AppendText(_("Receiving the buffer back from server ..."));
  500.   m_sock->Read(buf2, len * 1024);
  501.   m_text->AppendText(m_sock->Error() ? _("failed !\n") : _("done\n"));
  502.  
  503.   m_text->AppendText(_("Comparing the two buffers ..."));
  504.   if (memcmp(buf1, buf2, len) != 0)
  505.   {
  506.     m_text->AppendText(_("failed!\n"));
  507.     m_text->AppendText(_("Test 3 failed !\n"));
  508.   }
  509.   else
  510.   {
  511.     m_text->AppendText(_("done\n"));
  512.     m_text->AppendText(_("Test 3 passed !\n"));
  513.   }
  514.   m_text->AppendText(_("=== Test 3 ends ===\n"));
  515.  
  516.   delete[] buf2;
  517.   m_busy = FALSE;
  518.   UpdateStatusBar();
  519. }
  520.  
  521. void MyFrame::OnCloseConnection(wxCommandEvent& WXUNUSED(event))
  522. {
  523.   m_sock->Close();
  524.   UpdateStatusBar();
  525. }
  526.  
  527. void MyFrame::OnDatagram(wxCommandEvent& WXUNUSED(event))
  528. {
  529.   m_text->AppendText(_("\n=== Datagram test begins ===\n"));
  530.   m_text->AppendText(_("Sorry, not implemented\n"));
  531.   m_text->AppendText(_("=== Datagram test ends ===\n"));
  532. }
  533.  
  534. void MyFrame::OnTestURL(wxCommandEvent& WXUNUSED(event))
  535. {
  536.   // Note that we are creating a new socket here, so this
  537.   // won't mess with the client/server demo.
  538.  
  539.   // Ask for the URL
  540.   m_text->AppendText(_("\n=== URL test begins ===\n"));
  541.   wxString urlname = wxGetTextFromUser(_("Enter an URL to get"),
  542.                                        _("URL:"),
  543.                                        _T("http://localhost"));
  544.  
  545.   // Parse the URL
  546.   wxURL url(urlname);
  547.   if (url.GetError() != wxURL_NOERR)
  548.   {
  549.     m_text->AppendText(_("Error: couldn't parse URL\n"));
  550.     m_text->AppendText(_("=== URL test ends ===\n"));
  551.     return;
  552.   }
  553.  
  554.   // Try to get the input stream (connects to the given URL)
  555.   m_text->AppendText(_("Trying to establish connection...\n"));
  556.   wxYield();
  557.   wxInputStream *data = url.GetInputStream();
  558.   if (!data)
  559.   {
  560.     m_text->AppendText(_("Error: couldn't read from URL\n"));
  561.     m_text->AppendText(_("=== URL test ends ===\n"));
  562.     return;
  563.   }
  564.  
  565.   // Print the contents type and file size
  566.   wxString s;
  567.   s.Printf(_("Contents type: %s\nFile size: %i\nStarting to download...\n"),
  568.              url.GetProtocol().GetContentType().c_str(),
  569.              data->GetSize());
  570.   m_text->AppendText(s);
  571.   wxYield();
  572.  
  573.   // Get the data
  574.   wxFileOutputStream sout( wxT("test.url") );
  575.   if (!sout.Ok())
  576.   {
  577.     m_text->AppendText(_("Error: couldn't open file for output\n"));
  578.     m_text->AppendText(_("=== URL test ends ===\n"));
  579.     return;
  580.   }
  581.  
  582.   data->Read(sout);
  583.   m_text->AppendText(_("Results written to file: test.url\n"));
  584.   m_text->AppendText(_("Done.\n"));
  585.   m_text->AppendText(_("=== URL test ends ===\n"));
  586.  
  587.   delete data;
  588. }
  589.  
  590. void MyFrame::OnSocketEvent(wxSocketEvent& event)
  591. {
  592.   wxString s = _("OnSocketEvent: ");
  593.  
  594.   switch(event.GetSocketEvent())
  595.   {
  596.     case wxSOCKET_INPUT      : s.Append(_("wxSOCKET_INPUT\n")); break;
  597.     case wxSOCKET_LOST       : s.Append(_("wxSOCKET_LOST\n")); break;
  598.     case wxSOCKET_CONNECTION : s.Append(_("wxSOCKET_CONNECTION\n")); break;
  599.     default                  : s.Append(_("Unexpected event !\n")); break;
  600.   }
  601.  
  602.   m_text->AppendText(s);
  603.   UpdateStatusBar();
  604. }
  605.  
  606. // convenience functions
  607.  
  608. void MyFrame::UpdateStatusBar()
  609. {
  610.   wxString s;
  611.  
  612.   if (!m_sock->IsConnected())
  613.   {
  614.     s.Printf(_("Not connected"));
  615.   }
  616.   else
  617.   {
  618.     wxIPV4address addr;
  619.  
  620.     m_sock->GetPeer(addr);
  621.     s.Printf(_("%s : %d"), (addr.Hostname()).c_str(), addr.Service());
  622.   }
  623.  
  624.   SetStatusText(s, 1);
  625.  
  626.   m_menuSocket->Enable(CLIENT_OPEN, !m_sock->IsConnected() && !m_busy);
  627.   m_menuSocket->Enable(CLIENT_TEST1, m_sock->IsConnected() && !m_busy);
  628.   m_menuSocket->Enable(CLIENT_TEST2, m_sock->IsConnected() && !m_busy);
  629.   m_menuSocket->Enable(CLIENT_TEST3, m_sock->IsConnected() && !m_busy);
  630.   m_menuSocket->Enable(CLIENT_CLOSE, m_sock->IsConnected());
  631. }
  632.