Ubuntu下wxWidgets的CSocket编程,简单聊天室

服务器端

/////////////////////////////////////////////////////////////////////////////

// Name:        server.cpp

// Purpose:     Server for wxSocket demo

 

// Author:      Guillermo Rodriguez Garcia<guille@iies.es>

 

// Created:     1999/09/19

 

// Copyright:   (c) 1999 Guillermo Rodriguez Garcia

 

//              (c) 2009 Vadim Zeitlin

 

// Licence:     wxWindows licence

 

/////////////////////////////////////////////////////////////////////////////

 

 

 

//==========================================================================

 

// declarations

 

//==========================================================================

 

 

 

//--------------------------------------------------------------------------

 

// headers

 

//--------------------------------------------------------------------------

 

// For compilers that supportprecompilation, includes "wx/wx.h".

 

#include "wx/wxprec.h"

#ifdef __BORLANDC__

# pragma hdrstop

#endif

// for all others, include thenecessary headers

#ifndef WX_PRECOMP

# include "wx/wx.h"

#endif

#include "wx/busyinfo.h"

#include "wx/socket.h"

// this example is currently written touse only IP or only IPv6 sockets, it

// should be extended to allow usingeither in the future

#if wxUSE_IPV6

   typedef wxIPV6address IPaddress;

 

#else

 

   typedef wxIPV4address IPaddress;

 

#endif

 

//--------------------------------------------------------------------------

 

// resources

 

//--------------------------------------------------------------------------

 

 

 

// the application icon

 

#ifndef wxHAS_IMAGES_IN_RESOURCES

   //#include "../sample.xpm"

#endif

//--------------------------------------------------------------------------

// classes

//--------------------------------------------------------------------------

// Define a new application type

class MyApp : public wxApp

{

public:

 virtual bool OnInit();

};

// Define a new frame type: this isgoing to be our main frame

class MyFrame : public wxFrame

{

public:

 MyFrame();

 ~MyFrame();

 // event handlers (these functions should _not_ be virtual)

 void OnUDPTest(wxCommandEvent& event);

 void OnWaitForAccept(wxCommandEvent& event);

 void OnQuit(wxCommandEvent& event);

 void OnAbout(wxCommandEvent& event);

 void OnServerEvent(wxSocketEvent& event);

 void OnSocketEvent(wxSocketEvent& event);

 void Test1(wxSocketBase *sock);

 void Test2(wxSocketBase *sock);

 void Test3(wxSocketBase *sock);

// convenience functions

 void UpdateStatusBar();

private:

 wxSocketServer *m_server;

 wxTextCtrl     *m_text;

 wxMenu         *m_menuFile;

 wxMenuBar      *m_menuBar;

 bool            m_busy;

 int             m_numClients;

 // any class wishing to process wxWidgets events must use this macro

 DECLARE_EVENT_TABLE()

 

};

 

// simple helper class to log start andend of each test

class TestLogger

{

public:

   TestLogger(const wxString& name) : m_name(name)

   {

       wxLogMessage("=== %s begins ===", m_name);

   }

   ~TestLogger()

   {

       wxLogMessage("=== %s ends ===", m_name);

   }

private:

   const wxString m_name;

 

};

 

//--------------------------------------------------------------------------

// constants

//--------------------------------------------------------------------------

// IDs for the controls and the menucommands

enum

{

 // menu items 

SERVER_UDPTEST = 10,

 SERVER_WAITFORACCEPT,

 SERVER_QUIT = wxID_EXIT,

 SERVER_ABOUT = wxID_ABOUT,

 // id for sockets

 SERVER_ID = 100,

 SOCKET_ID

};

 

//--------------------------------------------------------------------------

 

// event tables and other macros forwxWidgets

 

//--------------------------------------------------------------------------

 

 

 

BEGIN_EVENT_TABLE(MyFrame, wxFrame)

 

 EVT_MENU(SERVER_QUIT, MyFrame::OnQuit)

 

 EVT_MENU(SERVER_ABOUT, MyFrame::OnAbout)

 

 EVT_MENU(SERVER_UDPTEST, MyFrame::OnUDPTest)

 

 EVT_MENU(SERVER_WAITFORACCEPT, MyFrame::OnWaitForAccept)

 

 EVT_SOCKET(SERVER_ID, MyFrame::OnServerEvent)

 

 EVT_SOCKET(SOCKET_ID, MyFrame::OnSocketEvent)

 

END_EVENT_TABLE()

 

 

 

IMPLEMENT_APP(MyApp)

 

 

 

 

 

//==========================================================================

 

// implementation

 

//==========================================================================

 

 

 

//--------------------------------------------------------------------------

 

// the application class

 

//--------------------------------------------------------------------------

 

 

 

bool MyApp::OnInit()

 

{

 

 if ( !wxApp::OnInit() )

 

     return false;

 

 

 

 // Create the main application window

 

 MyFrame *frame = new MyFrame();

 

 

 

 // Show it

 

 frame->Show(true);

 

 

 

 // Success

 

 return true;

 

}

 

 

 

//--------------------------------------------------------------------------

 

// main frame

 

//--------------------------------------------------------------------------

 

 

 

// frame constructor

 

 

 

MyFrame::MyFrame() : wxFrame((wxFrame*)NULL, wxID_ANY,

 

                             _("wxSocketdemo: Server"),

 

                             wxDefaultPosition,wxSize(300, 200))

 

{

 

 // Give the frame an icon

 

// SetIcon(wxICON(sample));

 

 

 

 // Make menus

 

 m_menuFile = new wxMenu();

 

 m_menuFile->Append(SERVER_WAITFORACCEPT, "&Wait forconnection\tCtrl-W");

 

 m_menuFile->Append(SERVER_UDPTEST, "&UDPtest\tCtrl-U");

 

 m_menuFile->AppendSeparator();

 

 m_menuFile->Append(SERVER_ABOUT, _("&About\tCtrl-A"),_("Show about dialog"));

 

 m_menuFile->AppendSeparator();

 

 m_menuFile->Append(SERVER_QUIT, _("E&xit\tAlt-X"),_("Quit server"));

 

 

 

 // Append menus to the menubar

 

 m_menuBar = new wxMenuBar();

 

 m_menuBar->Append(m_menuFile, _("&File"));

 

 SetMenuBar(m_menuBar);

 

 

 

#if wxUSE_STATUSBAR

 

 // Status bar

 

 CreateStatusBar(2);

 

#endif // wxUSE_STATUSBAR

 

 

 

 // Make a textctrl for logging

 

 m_text  = new wxTextCtrl(this,wxID_ANY,

 

                           _("Welcome towxSocket demo: Server\n"),

 

                           wxDefaultPosition,wxDefaultSize,

 

                           wxTE_MULTILINE | wxTE_READONLY);

 

 delete wxLog::SetActiveTarget(new wxLogTextCtrl(m_text));

 

 

 

 // Create the address - defaults to localhost:0 initially

 

 IPaddress addr;

 

 addr.Service(3000);

 

 

 

 wxLogMessage("Creating server at %s:%u", addr.IPAddress(),addr.Service());

 

 

 

 // Create the socket

 

 m_server = new wxSocketServer(addr);

 

 

 

 // We use IsOk() here to see if the server is really listening

 

 if (! m_server->IsOk())

 

 {

 

   wxLogMessage("Could not listen at the specified port !");

 

   return;

 

 }

 

 

 

 IPaddress addrReal;

 

 if ( !m_server->GetLocal(addrReal) )

 

 {

 

   wxLogMessage("ERROR: couldn't get the address we bound to");

 

 }

 

 else

 

 {

 

   wxLogMessage("Server listening at %s:%u",

 

                 addrReal.IPAddress(),addrReal.Service());

 

 }

 

 

 

 // Setup the event handler and subscribe to connection events

 

 m_server->SetEventHandler(*this, SERVER_ID);

 

 m_server->SetNotify(wxSOCKET_CONNECTION_FLAG);

 

 m_server->Notify(true);

 

 

 

 m_busy = false;

 

 m_numClients = 0;

 

 UpdateStatusBar();

 

}

 

 

 

MyFrame::~MyFrame()

 

{

 

 // No delayed deletion here, as the frame is dying anyway

 

 delete m_server;

 

}

 

 

 

// event handlers

 

 

 

voidMyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))

 

{

 

 // true is to force the frame to close

 

 Close(true);

 

}

 

 

 

voidMyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))

 

{

 

 wxMessageBox(_("wxSocket demo: Server\n(c) 1999 Guillermo RodriguezGarcia\n"),

 

               _("About Server"),

 

               wxOK | wxICON_INFORMATION,this);

 

}

 

 

 

voidMyFrame::OnUDPTest(wxCommandEvent& WXUNUSED(event))

 

{

 

   TestLogger logtest("UDP test");

 

 

 

   IPaddress addr;

 

   addr.Service(3000);

 

   wxDatagramSocket sock(addr);

 

 

 

   char buf[1024];

 

   size_t n = sock.RecvFrom(addr, buf, sizeof(buf)).LastCount();

 

   if ( !n )

 

   {

 

       wxLogMessage("ERROR: failed to receive data");

 

       return;

 

   }

 

 

 

   wxLogMessage("Received \"%s\" from %s:%u.",

 

                 wxString::From8BitData(buf,n),

 

                 addr.IPAddress(),addr.Service());

 

 

 

   for ( size_t i = 0; i < n; i++ )

 

   {

 

       char& c = buf[i];

 

       if ( (c >= 'A' && c <= 'M') || (c >= 'a' && c<= 'm') )

 

            c += 13;

 

       else if ( (c >= 'N' && c <= 'Z') || (c >= 'n'&& c <= 'z') )

 

            c -= 13;

 

   }

 

 

 

   if ( sock.SendTo(addr, buf, n).LastCount() != n )

 

   {

 

       wxLogMessage("ERROR: failed to send data");

 

       return;

 

   }

 

}

 

 

 

voidMyFrame::OnWaitForAccept(wxCommandEvent& WXUNUSED(event))

 

{

 

   TestLogger logtest("WaitForAccept() test");

 

 

 

   wxBusyInfo("Waiting for connection for 10 seconds...", this);

 

   if ( m_server->WaitForAccept(10) )

 

       wxLogMessage("Accepted client connection.");

 

   else

 

       wxLogMessage("Connection error or timeout expired.");

 

}

 

 

 

void MyFrame::Test1(wxSocketBase *sock)

 

{

 

 TestLogger logtest("Test 1");

 

 

 

 // Receive data from socket and send it back. We will first

 

 // get a byte with the buffer size, so we can specify the

 

 // exact size and use the wxSOCKET_WAITALL flag. Also, we

 

 // disabled input events so we won't have unwanted reentrance.

 

 // This way we can avoid the infamous wxSOCKET_BLOCK flag.

 

 

 

 sock->SetFlags(wxSOCKET_WAITALL);

 

 

 

 // Read the size

 

 unsigned char len;

 

 sock->Read(&len, 1);

 

 wxCharBuffer buf(len);

 

 

 

 // Read the data

 

 sock->Read(buf.data(), len);

 

 wxLogMessage("Got the data, sending it back");

 

 

 

 // Write it back

 

 sock->Write(buf, len);

 

}

 

 

 

void MyFrame::Test2(wxSocketBase *sock)

 

{

 

 char buf[4096];

 

 

 

 TestLogger logtest("Test 2");

 

 

 

 // We don't need to set flags because ReadMsg and WriteMsg

 

 // are not affected by them anyway.

 

 

 

 // Read the message

 

 wxUint32 len = sock->ReadMsg(buf, sizeof(buf)).LastCount();

 

 if ( !len )

 

 {

 

     wxLogError("Failed to read message.");

 

     return;

 

 }

 

 

 

 wxLogMessage("Got \"%s\" from client.",wxString::FromUTF8(buf, len));

 

 wxLogMessage("Sending the data back");

 

 

 

 // Write it back

 

 sock->WriteMsg(buf, len);

 

}

 

 

 

void MyFrame::Test3(wxSocketBase *sock)

 

{

 

 TestLogger logtest("Test 3");

 

 

 

 // This test is similar to the first one, but the len is

 

 // expressed in kbytes - this tests large data transfers.

 

 

 

 sock->SetFlags(wxSOCKET_WAITALL);

 

 

 

 // Read the size

 

 unsigned char len;

 

 sock->Read(&len, 1);

 

 wxCharBuffer buf(len*1024);

 

 

 

 // Read the data

 

 sock->Read(buf.data(), len * 1024);

 

 wxLogMessage("Got the data, sending it back");

 

 

 

 // Write it back

 

 sock->Write(buf, len * 1024);

 

}

 

 

 

voidMyFrame::OnServerEvent(wxSocketEvent& event)

 

{

 

 wxString s = _("OnServerEvent: ");

 

 wxSocketBase *sock;

 

 

 

 switch(event.GetSocketEvent())

 

 {

 

   case wxSOCKET_CONNECTION :s.Append(_("wxSOCKET_CONNECTION\n")); break;

 

   default                  :s.Append(_("Unexpected event !\n")); break;

 

 }

 

 

 

 m_text->AppendText(s);

 

 

 

 // Accept new connection if there is one in the pending

 

 // connections queue, else exit. We use Accept(false) for

 

 // non-blocking accept (although if we got here, there

 

 // should ALWAYS be a pending connection).

 

 

 

 sock = m_server->Accept(false);

 

 

 

 if (sock)

 

 {

 

   IPaddress addr;

 

   if ( !sock->GetPeer(addr) )

 

   {

 

     wxLogMessage("New connection from unknown client accepted.");

 

   }

 

   else

 

   {

 

     wxLogMessage("New client connection from %s:%u accepted",

 

                   addr.IPAddress(),addr.Service());

 

   }

 

 }

 

 else

 

 {

 

   wxLogMessage("Error: couldn't accept a new connection");

 

   return;

 

 }

 

 

 

 sock->SetEventHandler(*this, SOCKET_ID);

 

 sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);

 

 sock->Notify(true);

 

 

 

 m_numClients++;

 

 UpdateStatusBar();

 

}

 

 

 

voidMyFrame::OnSocketEvent(wxSocketEvent& event)

 

{

 

 wxString s = _("OnSocketEvent: ");

 

 wxSocketBase *sock = event.GetSocket();

 

 

 

 // First, print a message

 

 switch(event.GetSocketEvent())

 

 {

 

   case wxSOCKET_INPUT : s.Append(_("wxSOCKET_INPUT\n")); break;

 

   case wxSOCKET_LOST  :s.Append(_("wxSOCKET_LOST\n")); break;

 

   default             :s.Append(_("Unexpected event !\n")); break;

 

 }

 

 

 

 m_text->AppendText(s);

 

 

 

 // Now we process the event

 

 switch(event.GetSocketEvent())

 

 {

 

   case wxSOCKET_INPUT:

 

   {

 

     // We disable input events, so that the test doesn't trigger

 

     // wxSocketEvent again.

 

     sock->SetNotify(wxSOCKET_LOST_FLAG);

 

 

 

     // Which test are we going to run?

 

     unsigned char c;

 

     sock->Read(&c, 1);

 

 

 

     switch (c)

 

     {

 

       case 0xBE: Test1(sock); break;

 

       case 0xCE: Test2(sock); break;

 

       case 0xDE: Test3(sock); break;

 

       default:

 

          wxLogMessage("Unknown test idreceived from client");

 

     }

 

 

 

     // Enable input events again.

 

     sock->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);

 

     break;

 

   }

 

   case wxSOCKET_LOST:

 

   {

 

     m_numClients--;

 

 

 

     // Destroy() should be used instead of delete wherever possible,

 

     // due to the fact that wxSocket uses 'delayed events' (see the

 

     // documentation for wxPostEvent) and we don't want an event to

 

     // arrive to the event handler (the frame, here) after the socket

 

     // has been deleted. Also, we might be doing some other thing with

 

     // the socket at the same time; for example, we might be in the

 

     // middle of a test or something. Destroy() takes care of all

 

     // this for us.

 

 

 

     wxLogMessage("Deleting socket.");

 

     sock->Destroy();

 

     break;

 

   }

 

   default: ;

 

 }

 

 

 

 UpdateStatusBar();

 

}

 

 

 

// convenience functions

 

 

 

void MyFrame::UpdateStatusBar()

 

{

 

#if wxUSE_STATUSBAR

 

 wxString s;

 

 s.Printf(_("%d clients connected"), m_numClients);

 

 SetStatusText(s, 1);

 

#endif // wxUSE_STATUSBAR

 

}

客户端

/////////////////////////////////////////////////////////////////////////////

 

// Name:        client.cpp

 

// Purpose:     Client for wxSocket demo

 

// Author:      Guillermo Rodriguez Garcia<guille@iies.es>

 

// Modified by:

 

// Created:     1999/09/19

 

// Copyright:   (c) 1999 Guillermo Rodriguez Garcia

 

// Licence:     wxWindows licence

 

/////////////////////////////////////////////////////////////////////////////

 

 

 

//==========================================================================

 

// declarations

 

//==========================================================================

 

 

 

// --------------------------------------------------------------------------

 

// headers

 

//--------------------------------------------------------------------------

 

 

 

// For compilers that supportprecompilation, includes "wx/wx.h".

 

#include "wx/wxprec.h"

 

 

 

#ifdef __BORLANDC__

 

# pragma hdrstop

 

#endif

 

 

 

// for all others, include thenecessary headers

 

#ifndef WX_PRECOMP

 

# include "wx/wx.h"

 

#endif

 

 

 

#include "wx/socket.h"

 

#include "wx/url.h"

 

#include "wx/sstream.h"

 

#include <memory>

 

 

 

//--------------------------------------------------------------------------

 

// resources

 

//--------------------------------------------------------------------------

 

 

 

// the application icon

 

#ifndef wxHAS_IMAGES_IN_RESOURCES

 

   //#include "../sample.xpm"

 

#endif

 

 

 

//--------------------------------------------------------------------------

 

// classes

 

//--------------------------------------------------------------------------

 

 

 

// Define a new application type

 

class MyApp : public wxApp

 

{

 

public:

 

 virtual bool OnInit();

 

};

 

 

 

// Define a new frame type: this isgoing to be our main frame

 

class MyFrame : public wxFrame

 

{

 

public:

 

 MyFrame();

 

 ~MyFrame();

 

 

 

 // event handlers for File menu

 

 void OnQuit(wxCommandEvent& event);

 

 void OnAbout(wxCommandEvent& event);

 

 

 

 // event handlers for Socket menu

 

 void OnOpenConnection(wxCommandEvent& event);

 

 void OnTest1(wxCommandEvent& event);

 

 void OnTest2(wxCommandEvent& event);

 

 void OnTest3(wxCommandEvent& event);

 

 void OnCloseConnection(wxCommandEvent& event);

 

 

 

#if wxUSE_URL

 

 // event handlers for Protocols menu

 

 void OnTestURL(wxCommandEvent& event);

 

#endif

 

#if wxUSE_IPV6

 

 void OnOpenConnectionIPv6(wxCommandEvent& event);

 

#endif

 

 

 

 void OpenConnection(wxSockAddress::Family family);

 

 

 

 // event handlers for DatagramSocket menu (stub)

 

 void OnDatagram(wxCommandEvent& event);

 

 

 

 // socket event handler

 

 void OnSocketEvent(wxSocketEvent& event);

 

 

 

 // convenience functions

 

 void UpdateStatusBar();

 

 

 

private:

 

 wxSocketClient *m_sock;

 

 wxTextCtrl     *m_text;

 

 wxMenu         *m_menuFile;

 

 wxMenu         *m_menuSocket;

 

 wxMenu        *m_menuDatagramSocket;

 

 wxMenu         *m_menuProtocols;

 

 wxMenuBar      *m_menuBar;

 

 bool            m_busy;

 

 

 

 // any class wishing to process wxWidgets events must use this macro

 

 DECLARE_EVENT_TABLE()

 

};

 

 

 

// simple helper class to log start andend of each test

 

class TestLogger

 

{

 

public:

 

   TestLogger(const wxString& name) : m_name(name)

 

   {

 

       wxLogMessage("=== %s test begins ===", m_name);

 

   }

 

 

 

   ~TestLogger()

 

   {

 

       wxLogMessage("=== %s test ends ===", m_name);

 

   }

 

 

 

private:

 

   const wxString m_name;

 

};

 

 

 

//--------------------------------------------------------------------------

 

// constants

 

//--------------------------------------------------------------------------

 

 

 

// IDs for the controls and the menucommands

 

enum

 

{

 

 // menu items

 

 CLIENT_QUIT = wxID_EXIT,

 

 CLIENT_ABOUT = wxID_ABOUT,

 

 CLIENT_OPEN = 100,

 

#if wxUSE_IPV6

 

 CLIENT_OPENIPV6,

 

#endif

 

 CLIENT_TEST1,

 

 CLIENT_TEST2,

 

 CLIENT_TEST3,

 

 CLIENT_CLOSE,

 

#if wxUSE_URL

 

 CLIENT_TESTURL,

 

#endif

 

 CLIENT_DGRAM,

 

 

 

 // id for socket

 

 SOCKET_ID

 

};

 

 

 

//--------------------------------------------------------------------------

 

// event tables and other macros forwxWidgets

 

//--------------------------------------------------------------------------

 

 

 

BEGIN_EVENT_TABLE(MyFrame, wxFrame)

 

 EVT_MENU(CLIENT_QUIT,    MyFrame::OnQuit)

 

 EVT_MENU(CLIENT_ABOUT,   MyFrame::OnAbout)

 

 EVT_MENU(CLIENT_OPEN,    MyFrame::OnOpenConnection)

 

#if wxUSE_IPV6

 

 EVT_MENU(CLIENT_OPENIPV6, MyFrame::OnOpenConnectionIPv6)

 

#endif

 

 EVT_MENU(CLIENT_TEST1,   MyFrame::OnTest1)

 

 EVT_MENU(CLIENT_TEST2,   MyFrame::OnTest2)

 

 EVT_MENU(CLIENT_TEST3,   MyFrame::OnTest3)

 

 EVT_MENU(CLIENT_CLOSE,   MyFrame::OnCloseConnection)

 

 EVT_MENU(CLIENT_DGRAM,   MyFrame::OnDatagram)

 

#if wxUSE_URL

 

 EVT_MENU(CLIENT_TESTURL, MyFrame::OnTestURL)

 

#endif

 

 EVT_SOCKET(SOCKET_ID,    MyFrame::OnSocketEvent)

 

END_EVENT_TABLE()

 

 

 

IMPLEMENT_APP(MyApp)

 

 

 

//==========================================================================

 

// implementation

 

//==========================================================================

 

 

 

//--------------------------------------------------------------------------

 

// the application class

 

//--------------------------------------------------------------------------

 

 

 

bool MyApp::OnInit()

 

{

 

 if ( !wxApp::OnInit() )

 

     return false;

 

 

 

 // Create the main application window

 

 MyFrame *frame = new MyFrame();

 

 

 

 // Show it

 

 frame->Show(true);

 

 

 

 // success

 

 return true;

 

}

 

 

 

//--------------------------------------------------------------------------

 

// main frame

 

//--------------------------------------------------------------------------

 

 

 

// frame constructor

 

MyFrame::MyFrame() : wxFrame((wxFrame*)NULL, wxID_ANY,

 

                            _("wxSocketdemo: Client"),

 

                             wxDefaultPosition,wxSize(300, 200))

 

{

 

 // Give the frame an icon

 

 //SetIcon(wxICON(sample));

 

 

 

 // Make menus

 

 m_menuFile = new wxMenu();

 

 m_menuFile->Append(CLIENT_ABOUT, _("&About\tCtrl-A"),_("Show about dialog"));

 

 m_menuFile->AppendSeparator();

 

 m_menuFile->Append(CLIENT_QUIT, _("E&xit\tAlt-X"),_("Quit client"));

 

 

 

 m_menuSocket = new wxMenu();

 

 m_menuSocket->Append(CLIENT_OPEN, _("&Open session\tCtrl-O"),_("Connect to server"));

 

#if wxUSE_IPV6

 

 m_menuSocket->Append(CLIENT_OPENIPV6, _("&Opensession(IPv6)\tShift-Ctrl-O"), _("Connect to server(IPv6)"));

 

#endif

 

 m_menuSocket->AppendSeparator();

 

 m_menuSocket->Append(CLIENT_TEST1, _("Test&1\tCtrl-F1"), _("Test basic functionality"));

 

 m_menuSocket->Append(CLIENT_TEST2, _("Test&2\tCtrl-F2"), _("Test ReadMsg and WriteMsg"));

 

 m_menuSocket->Append(CLIENT_TEST3, _("Test&3\tCtrl-F3"), _("Test large data transfer"));

 

 m_menuSocket->AppendSeparator();

 

 m_menuSocket->Append(CLIENT_CLOSE, _("&Closesession\tCtrl-Q"), _("Close connection"));

 

 

 

 m_menuDatagramSocket = new wxMenu();

 

 m_menuDatagramSocket->Append(CLIENT_DGRAM, _("&Datagramtest\tCtrl-D"), _("Test UDP sockets"));

 

 

 

#if wxUSE_URL

 

 m_menuProtocols = new wxMenu();

 

 m_menuProtocols->Append(CLIENT_TESTURL, _("TestURL\tCtrl-U"),

 

                          _("Get data fromthe specified URL"));

 

#endif

 

 

 

 // Append menus to the menubar

 

 m_menuBar = new wxMenuBar();

 

 m_menuBar->Append(m_menuFile, _("&File"));

 

 m_menuBar->Append(m_menuSocket, _("&TCP"));

 

 m_menuBar->Append(m_menuDatagramSocket, _("&UDP"));

 

#if wxUSE_URL

 

 m_menuBar->Append(m_menuProtocols, _("&Protocols"));

 

#endif

 

 SetMenuBar(m_menuBar);

 

 

 

#if wxUSE_STATUSBAR

 

 // Status bar

 

 CreateStatusBar(2);

 

#endif // wxUSE_STATUSBAR

 

 

 

 // Make a textctrl for logging

 

 m_text  = new wxTextCtrl(this,wxID_ANY,

 

                           _("Welcome towxSocket demo: Client\nClient ready\n"),

 

                           wxDefaultPosition,wxDefaultSize,

 

                           wxTE_MULTILINE |wxTE_READONLY);

 

 delete wxLog::SetActiveTarget(new wxLogTextCtrl(m_text));

 

 

 

 // Create the socket

 

 m_sock = new wxSocketClient();

 

 

 

 // Setup the event handler and subscribe to most events

 

 m_sock->SetEventHandler(*this, SOCKET_ID);

 

 m_sock->SetNotify(wxSOCKET_CONNECTION_FLAG |

 

                    wxSOCKET_INPUT_FLAG |

 

                    wxSOCKET_LOST_FLAG);

 

 m_sock->Notify(true);

 

 

 

 m_busy = false;

 

 UpdateStatusBar();

 

}

 

 

 

MyFrame::~MyFrame()

 

{

 

 // No delayed deletion here, as the frame is dying anyway

 

 delete m_sock;

 

}

 

 

 

// event handlers

 

 

 

voidMyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))

 

{

 

 // true is to force the frame to close

 

 Close(true);

 

}

 

 

 

voidMyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))

 

{

 

 wxMessageBox(_("wxSocket demo: Client\n(c) 1999 Guillermo RodriguezGarcia\n"),

 

               _("About Client"),

 

               wxOK | wxICON_INFORMATION,this);

 

}

 

 

 

voidMyFrame::OnOpenConnection(wxCommandEvent& WXUNUSED(event))

 

{

 

   OpenConnection(wxSockAddress::IPV4);

 

}

 

#if wxUSE_IPV6

 

voidMyFrame::OnOpenConnectionIPv6(wxCommandEvent& WXUNUSED(event))

 

{

 

   OpenConnection(wxSockAddress::IPV6);

 

}

 

#endif // wxUSE_IPV6

 

 

 

voidMyFrame::OpenConnection(wxSockAddress::Family family)

 

{

 

   wxUnusedVar(family); // unused in !wxUSE_IPV6 case

 

 

 

 wxIPaddress * addr;

 

 wxIPV4address addr4;

 

#if wxUSE_IPV6

 

 wxIPV6address addr6;

 

 if ( family == wxSockAddress::IPV6 )

 

   addr = &addr6;

 

 else

 

#endif

 

   addr = &addr4;

 

 

 

 m_menuSocket->Enable(CLIENT_OPEN, false);

 

#if wxUSE_IPV6

 

 m_menuSocket->Enable(CLIENT_OPENIPV6, false);

 

#endif

 

 m_menuSocket->Enable(CLIENT_CLOSE, false);

 

 

 

 // Ask user for server address

 

 wxString hostname = wxGetTextFromUser(

 

   _("Enter the address of the wxSocket demo server:"),

 

   _("Connect ..."),

 

   _("localhost"));

 

 if ( hostname.empty() )

 

   return;

 

 

 

 addr->Hostname(hostname);

 

 addr->Service(3000);

 

 

 

 // we connect asynchronously and will get a wxSOCKET_CONNECTION eventwhen

 

 // the connection is really established

 

 //

 

 // if you want to make sure that connection is established right hereyou

 

 // could call WaitOnConnect(timeout) instead

 

 wxLogMessage("Trying to connect to %s:%d", hostname,addr->Service());

 

 

 

 m_sock->Connect(*addr, false);

 

}

 

 

 

void MyFrame::OnTest1(wxCommandEvent&WXUNUSED(event))

 

{

 

 // Disable socket menu entries (exception: Close Session)

 

 m_busy = true;

 

 UpdateStatusBar();

 

 

 

 m_text->AppendText(_("\n=== Test 1 begins ===\n"));

 

 

 

 // Tell the server which test we are running

 

 unsigned char c = 0xBE;

 

 m_sock->Write(&c, 1);

 

 

 

 // Send some data and read it back. We know the size of the

 

 // buffer, so we can specify the exact number of bytes to be

 

 // sent or received and use the wxSOCKET_WAITALL flag. Also,

 

 // we have disabled menu entries which could interfere with

 

 // the test, so we can safely avoid the wxSOCKET_BLOCK flag.

 

 //

 

 // First we send a byte with the length of the string, then

 

 // we send the string itself (do NOT try to send any integral

 

 // value larger than a byte "as is" across the network, or

 

 // you might be in trouble! Ever heard about big and little

 

 // endian computers?)

 

 

 

 m_sock->SetFlags(wxSOCKET_WAITALL);

 

 

 

 const char *buf1 = "Test string (less than 256 chars!)";

 

 unsigned char len  = (unsignedchar)(wxStrlen(buf1) + 1);

 

 wxCharBuffer buf2(wxStrlen(buf1));

 

 

 

 m_text->AppendText(_("Sending a test buffer to the server..."));

 

 m_sock->Write(&len, 1);

 

 m_sock->Write(buf1, len);

 

 m_text->AppendText(m_sock->Error() ? _("failed !\n") :_("done\n"));

 

 

 

 m_text->AppendText(_("Receiving the buffer back from server..."));

 

 m_sock->Read(buf2.data(), len);

 

 m_text->AppendText(m_sock->Error() ? _("failed !\n") :_("done\n"));

 

 

 

 m_text->AppendText(_("Comparing the two buffers ..."));

 

 if (memcmp(buf1, buf2, len) != 0)

 

 {

 

   m_text->AppendText(_("failed!\n"));

 

   m_text->AppendText(_("Test 1 failed !\n"));

 

 }

 

 else

 

 {

 

   m_text->AppendText(_("done\n"));

 

   m_text->AppendText(_("Test 1 passed !\n"));

 

 }

 

 m_text->AppendText(_("=== Test 1 ends ===\n"));

 

 

 

 m_busy = false;

 

 UpdateStatusBar();

 

}

 

 

 

voidMyFrame::OnTest2(wxCommandEvent& WXUNUSED(event))

 

{

 

 // Disable socket menu entries (exception: Close Session)

 

 m_busy = true;

 

 UpdateStatusBar();

 

 

 

 m_text->AppendText(_("\n=== Test 2 begins ===\n"));

 

 

 

 // Tell the server which test we are running

 

 unsigned char c = 0xCE;

 

 m_sock->Write(&c, 1);

 

 

 

 // Here we use ReadMsg and WriteMsg to send messages with

 

 // a header with size information. Also, the reception is

 

 // event triggered, so we test input events as well.

 

 //

 

 // We need to set no flags here (ReadMsg and WriteMsg are

 

 // not affected by flags)

 

 

 

 m_sock->SetFlags(wxSOCKET_WAITALL);

 

 

 

 wxString s = wxGetTextFromUser(

 

   _("Enter an arbitrary string to send to the server:"),

 

   _("Test 2 ..."),

 

   _("Yes I like wxWidgets!"));

 

 

 

 const wxScopedCharBuffer msg1(s.utf8_str());

 

 size_t len  = wxStrlen(msg1) + 1;

 

 wxCharBuffer msg2(wxStrlen(msg1));

 

 

 

 m_text->AppendText(_("Sending the string with WriteMsg..."));

 

 m_sock->WriteMsg(msg1, len);

 

 m_text->AppendText(m_sock->Error() ? _("failed !\n") :_("done\n"));

 

 m_text->AppendText(_("Waiting for an event (timeout = 2sec)\n"));

 

 

 

 // Wait until data available (will also return if the connection islost)

 

 m_sock->WaitForRead(2);

 

 

 

 if (m_sock->IsData())

 

 {

 

   m_text->AppendText(_("Reading the string back with ReadMsg..."));

 

   m_sock->ReadMsg(msg2.data(), len);

 

   m_text->AppendText(m_sock->Error() ? _("failed !\n") :_("done\n"));

 

   m_text->AppendText(_("Comparing the two buffers ..."));

 

   if (memcmp(msg1, msg2, len) != 0)

 

   {

 

     m_text->AppendText(_("failed!\n"));

 

     m_text->AppendText(_("Test 2 failed !\n"));

 

   }

 

   else

 

   {

 

     m_text->AppendText(_("done\n"));

 

     m_text->AppendText(_("Test 2 passed !\n"));

 

   }

 

 }

 

 else

 

   m_text->AppendText(_("Timeout ! Test 2 failed.\n"));

 

 

 

 m_text->AppendText(_("=== Test 2 ends ===\n"));

 

 

 

 m_busy = false;

 

 UpdateStatusBar();

 

}

 

 

 

voidMyFrame::OnTest3(wxCommandEvent& WXUNUSED(event))

 

{

 

 // Disable socket menu entries (exception: Close Session)

 

 m_busy = true;

 

 UpdateStatusBar();

 

 

 

 m_text->AppendText(_("\n=== Test 3 begins ===\n"));

 

 

 

 // Tell the server which test we are running

 

 unsigned char c = 0xDE;

 

 m_sock->Write(&c, 1);

 

 

 

 // This test also is similar to the first one but it sends a

 

 // large buffer so that wxSocket is actually forced to split

 

 // it into pieces and take care of sending everything before

 

 // returning.

 

 

 

 m_sock->SetFlags(wxSOCKET_WAITALL);

 

 

 

 // Note that len is in kbytes here!

 

 const unsigned char len  = 32;

 

 wxCharBuffer buf1(len * 1024),

 

               buf2(len * 1024);

 

 

 

 for (size_t i = 0; i < len * 1024; i ++)

 

   buf1.data()[i] = (char)(i % 256);

 

 

 

 m_text->AppendText(_("Sending a large buffer (32K) to the server..."));

 

 m_sock->Write(&len, 1);

 

 m_sock->Write(buf1, len * 1024);

 

 m_text->AppendText(m_sock->Error() ? _("failed !\n") :_("done\n"));

 

 

 

 m_text->AppendText(_("Receiving the buffer back from server..."));

 

 m_sock->Read(buf2.data(), len * 1024);

 

 m_text->AppendText(m_sock->Error() ? _("failed !\n") :_("done\n"));

 

 

 

 m_text->AppendText(_("Comparing the two buffers ..."));

 

 if (memcmp(buf1, buf2, len) != 0)

 

 {

 

   m_text->AppendText(_("failed!\n"));

 

   m_text->AppendText(_("Test 3 failed !\n"));

 

 }

 

 else

 

 {

 

   m_text->AppendText(_("done\n"));

 

   m_text->AppendText(_("Test 3 passed !\n"));

 

 }

 

 m_text->AppendText(_("=== Test 3 ends ===\n"));

 

 

 

 m_busy = false;

 

 UpdateStatusBar();

 

}

 

 

 

voidMyFrame::OnCloseConnection(wxCommandEvent& WXUNUSED(event))

 

{

 

 m_sock->Close();

 

 UpdateStatusBar();

 

}

 

 

 

voidMyFrame::OnDatagram(wxCommandEvent& WXUNUSED(event))

 

{

 

   wxString hostname = wxGetTextFromUser

 

                        (

 

                         "Enter theaddress of the wxSocket demo server:",

 

                         "UDP peer",

 

                         "localhost"

 

                        );

 

   if ( hostname.empty() )

 

       return;

 

 

 

   TestLogger logtest("UDP");

 

 

 

   wxIPV4address addrLocal;

 

   addrLocal.Hostname();

 

   wxDatagramSocket sock(addrLocal);

 

   if ( !sock.IsOk() )

 

   {

 

       wxLogMessage("ERROR: failed to create UDP socket");

 

       return;

 

   }

 

 

 

   wxLogMessage("Created UDP socket at %s:%u",

 

                 addrLocal.IPAddress(),addrLocal.Service());

 

 

 

   wxIPV4address addrPeer;

 

   addrPeer.Hostname(hostname);

 

   addrPeer.Service(3000);

 

 

 

   wxLogMessage("Testing UDP with peer at %s:%u",

 

                 addrPeer.IPAddress(),addrPeer.Service());

 

 

 

   char buf[] = "Uryyb sebz pyvrag!";

 

   if ( sock.SendTo(addrPeer, buf, sizeof(buf)).LastCount() != sizeof(buf))

 

   {

 

       wxLogMessage("ERROR: failed to send data");

 

       return;

 

   }

 

 

 

   if ( sock.RecvFrom(addrPeer, buf, sizeof(buf)).LastCount() !=sizeof(buf) )

 

   {

 

       wxLogMessage("ERROR: failed to receive data");

 

       return;

 

   }

 

 

 

   wxLogMessage("Received \"%s\" from %s:%u.",

 

                 wxString::From8BitData(buf,sock.LastCount()),

 

                 addrPeer.IPAddress(),addrPeer.Service());

 

}

 

 

 

#if wxUSE_URL

 

 

 

voidMyFrame::OnTestURL(wxCommandEvent& WXUNUSED(event))

 

{

 

   // Ask for the URL

 

   static wxString s_urlname("http://www.google.com/");

 

   wxString urlname = wxGetTextFromUser

 

                       (

 

                        _("Enter an URL toget"),

 

                        _("URL:"),

 

                        s_urlname

 

                       );

 

   if ( urlname.empty() )

 

       return; // cancelled by user

 

 

 

   s_urlname = urlname;

 

 

 

 

 

   TestLogger logtest("URL");

 

 

 

   // Parse the URL

 

   wxURL url(urlname);

 

   if ( url.GetError() != wxURL_NOERR )

 

   {

 

       wxLogError("Failed to parse URL \"%s\"", urlname);

 

       return;

 

   }

 

 

 

   // Try to get the input stream (connects to the given URL)

 

   wxLogMessage("Establishing connection to \"%s\"...",urlname);

 

   const std::auto_ptr<wxInputStream> data(url.GetInputStream());

 

   if ( !data.get() )

 

   {

 

       wxLogError("Failed to retrieve URL \"%s\"",urlname);

 

       return;

 

   }

 

 

 

   // Print the contents type and file size

 

   wxLogMessage("Contents type: %s\nFile size: %lu\nStarting todownload...",

 

                url.GetProtocol().GetContentType(),

 

                 static_cast<unsignedlong>( data->GetSize() ));

 

 

 

   // Get the data

 

   wxStringOutputStream sout;

 

   if ( data->Read(sout).GetLastError() != wxSTREAM_EOF )

 

   {

 

       wxLogError("Error reading the input stream.");

 

   }

 

 

 

   wxLogMessage("Text retrieved from URL \"%s\"follows:\n%s",

 

                 urlname, sout.GetString());

 

}

 

 

 

#endif // wxUSE_URL

 

 

 

voidMyFrame::OnSocketEvent(wxSocketEvent& event)

 

{

 

   switch ( event.GetSocketEvent() )

 

   {

 

       case wxSOCKET_INPUT:

 

            wxLogMessage("Input availableon the socket");

 

            break;

 

 

 

       case wxSOCKET_LOST:

 

            wxLogMessage("Socketconnection was unexpectedly lost.");

 

            UpdateStatusBar();

 

            break;

 

 

 

       case wxSOCKET_CONNECTION:

 

            wxLogMessage("... socket isnow connected.");

 

            UpdateStatusBar();

 

            break;

 

 

 

       default:

 

            wxLogMessage("Unknown socketevent!!!");

 

            break;

 

   }

 

}

 

 

 

// convenience functions

 

 

 

void MyFrame::UpdateStatusBar()

 

{

 

#if wxUSE_STATUSBAR

 

 wxString s;

 

 

 

 if (!m_sock->IsConnected())

 

 {

 

   s = "Not connected";

 

 }

 

 else

 

 {

 

#if wxUSE_IPV6

 

   wxIPV6address addr;

 

#else

 

   wxIPV4address addr;

 

#endif

 

 

 

   m_sock->GetPeer(addr);

 

   s.Printf("%s : %d", addr.Hostname(), addr.Service());

 

 }

 

 

 

 SetStatusText(s, 1);

 

#endif // wxUSE_STATUSBAR

 

 

 

 m_menuSocket->Enable(CLIENT_OPEN, !m_sock->IsConnected()&& !m_busy);

 

#if wxUSE_IPV6

 

 m_menuSocket->Enable(CLIENT_OPENIPV6, !m_sock->IsConnected()&& !m_busy);

 

#endif

 

 m_menuSocket->Enable(CLIENT_TEST1, m_sock->IsConnected()&& !m_busy);

 

 m_menuSocket->Enable(CLIENT_TEST2, m_sock->IsConnected()&& !m_busy);

 

 m_menuSocket->Enable(CLIENT_TEST3, m_sock->IsConnected()&& !m_busy);

 

 m_menuSocket->Enable(CLIENT_CLOSE, m_sock->IsConnected());

 

}

 

posted @ 2014-04-16 10:49  ZhangAihua  阅读(581)  评论(0编辑  收藏  举报