wxWidgets

Socket

Il progetto che si propone di sviluppare è suddiviso in tre parti:

  1. Una comunicazione tra un server e uno o più client. In questo primo progetto il Server è in grado di inviare messaggi solo all'ultimo client da cui ha ricevuto un pacchetto.

  2. Una gestione di connessioni multiple da parte del server.
    In questo progetto il Server memorizza gli indirizzi dei client, quindi può scegliere a chi inviare un messaggio e può riconoscere il client che si disconnette.

  3. Un gioco in rete.

Tombola in rete

Avviare un nuovo progetto wxDev-C++ e denominarlo Tombola

L'interfaccia in figura è composta da un wxFlexGridSizer che funge da contenitore per tutti i componenti:

  1. un wxPanel per disegnare la tombola.

  2. un wxMemo per evidenziare le combinazioni vincenti uscite.

  3. un wxButton per estrarre un numero.

  4. un wxStaticTextBox per intitolare la casella sottostante.

  5. un wxButton per mettere il server in ascolto.

  6. un wxListBox per elencare gli utenti connessi.

  7. un wxStaticText per segnalare l'indirizzo IP e la porta di ascolto del server.

  8. un wxEdit per inserire l'indirizzo IP della macchina su cui si esegue l'applicazione.

Al componente frame bisogna abilitare la gestione degli eventi onPaint.

L'applicazione Server.

il file TombolaFrm.h


///-----------------------------------------------------------------
///
/// @file      TombolaFrm.h
/// @author    Pc
/// Created:   25/11/2013 19:48:35
/// @section   DESCRIPTION
///            TombolaFrm class declaration
///
///------------------------------------------------------------------

#ifndef __TOMBOLAFRM_H__
#define __TOMBOLAFRM_H__

#ifdef __BORLANDC__
	#pragma hdrstop
#endif

#ifndef WX_PRECOMP
	#include <wx/wx.h>
	#include <wx/frame.h>
#else
	#include <wx/wxprec.h>
#endif

//Do not add custom headers between 
//Header Include Start and Header Include End.
//wxDev-C++ designer will remove them. Add custom headers after the block.
////Header Include Start
#include <wx/listbox.h>
#include <wx/stattext.h>
#include <wx/button.h>
#include <wx/textctrl.h>
#include <wx/panel.h>
#include <wx/sizer.h>
////Header Include End

////Dialog Style Start
#undef TombolaFrm_STYLE
#define TombolaFrm_STYLE wxCAPTION | wxSYSTEM_MENU | wxMINIMIZE_BOX | wxCLOSE_BOX
////Dialog Style End
#include <wx/socket.h>
class TombolaFrm : public wxFrame
{
    private:
        int Urna[90], NrDentro, punteggi[18];
        int prossVinc;
        wxString cartella[24];
        wxSocketServer *server;
        wxSocketBase *client[20];
        int nrClient;
	private:
		DECLARE_EVENT_TABLE();
		
	public:
		TombolaFrm(wxWindow *parent, wxWindowID id = 1, const wxString &title = wxT("Tombola"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = TombolaFrm_STYLE);
		virtual ~TombolaFrm();
		void TombolaFrmPaint(wxPaintEvent& event);
		void WxButton1Click(wxCommandEvent& event);
		void OnServerEvent(wxSocketEvent& event);
		void OnSocketEvent(wxSocketEvent& event);
		void WxButton2Click(wxCommandEvent& event);
	private:
		//Do not add custom control declarations between
		//GUI Control Declaration Start and GUI Control Declaration End.
		//wxDev-C++ will remove them. Add custom code after the block.
		////GUI Control Declaration Start
		wxTextCtrl *WxEdit1;
		wxStaticText *WxStaticText2;
		wxListBox *WxListBox1;
		wxButton *WxButton2;
		wxStaticText *WxStaticText1;
		wxButton *WxButton1;
		wxTextCtrl *WxMemo1;
		wxPanel *WxPanel1;
		wxFlexGridSizer *WxFlexGridSizer1;
		////GUI Control Declaration End
		
	private:
		//Note: if you receive any error with these enum IDs, then you need to
		//change your old form code that are based on the #define control IDs.
		//#defines may replace a numeric value for the enum names.
		//Try copy and pasting the below block in your old form header files.
		enum
		{
			////GUI Enum Control ID Start
			ID_WXEDIT1 = 1010,
			ID_WXSTATICTEXT2 = 1009,
			ID_WXLISTBOX1 = 1008,
			ID_WXBUTTON2 = 1007,
			ID_WXSTATICTEXT1 = 1006,
			ID_WXBUTTON1 = 1005,
			ID_WXMEMO1 = 1004,
			ID_WXPANEL1 = 1002,
			////GUI Enum Control ID End
			SERVER_ID,
			SOCKET_ID,
			ID_DUMMY_VALUE_ //don't remove this value unless you have other enum values
		};
		
	private:
		void OnClose(wxCloseEvent& event);
		void CreateGUIControls();
};

#endif

Il file TombolaFrm.cpp


///-----------------------------------------------------------------
///
/// @file      TombolaFrm.cpp
/// @author    Pc
/// Created:   25/11/2013 19:48:35
/// @section   DESCRIPTION
///            TombolaFrm class implementation
///
///------------------------------------------------------------------

#include "TombolaFrm.h"

//Do not add custom headers between
//Header Include Start and Header Include End
//wxDev-C++ designer will remove them
////Header Include Start
////Header Include End

//----------------------------------------------------------------------------
// TombolaFrm
//----------------------------------------------------------------------------
//Add Custom Events only in the appropriate block.
//Code added in other places will be removed by wxDev-C++
////Event Table Start
BEGIN_EVENT_TABLE(TombolaFrm,wxFrame)
	////Manual Code Start
	EVT_SOCKET(SERVER_ID, TombolaFrm::OnServerEvent)
	EVT_SOCKET(SOCKET_ID, TombolaFrm::OnSocketEvent)
	////Manual Code End
	
	EVT_CLOSE(TombolaFrm::OnClose)
	EVT_PAINT(TombolaFrm::TombolaFrmPaint)
	EVT_BUTTON(ID_WXBUTTON2,TombolaFrm::WxButton2Click)
	EVT_BUTTON(ID_WXBUTTON1,TombolaFrm::WxButton1Click)
END_EVENT_TABLE()
////Event Table End

TombolaFrm::TombolaFrm(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
: wxFrame(parent, id, title, position, size, style)
{
	CreateGUIControls();
}

TombolaFrm::~TombolaFrm()
{
}

void TombolaFrm::CreateGUIControls()
{
	//Do not add custom code between
	//GUI Items Creation Start and GUI Items Creation End
	//wxDev-C++ designer will remove them.
	//Add the custom code before or after the blocks
	////GUI Items Creation Start

	WxFlexGridSizer1 = new wxFlexGridSizer(0, 2, 0, 0);
	this->SetSizer(WxFlexGridSizer1);
	this->SetAutoLayout(true);

	WxPanel1 = new wxPanel(this, ID_WXPANEL1, wxPoint(5, 5), wxSize(281, 201));
	WxFlexGridSizer1->Add(WxPanel1, 0, wxALIGN_CENTER | wxALL, 5);

	WxMemo1 = new wxTextCtrl(this, ID_WXMEMO1, wxEmptyString, wxPoint(296, 45), wxSize(185, 121), wxTE_MULTILINE, wxDefaultValidator, _("WxMemo1"));
	WxMemo1->SetMaxLength(0);
	WxMemo1->AppendText(_("Vincite"));
	WxMemo1->SetFocus();
	WxMemo1->SetInsertionPointEnd();
	WxFlexGridSizer1->Add(WxMemo1, 0, wxALIGN_CENTER | wxALL, 5);

	WxButton1 = new wxButton(this, ID_WXBUTTON1, _("Estrai"), wxPoint(108, 216), wxSize(75, 25), 0, wxDefaultValidator, _("WxButton1"));
	WxFlexGridSizer1->Add(WxButton1, 0, wxALIGN_CENTER | wxALL, 5);

	WxStaticText1 = new wxStaticText(this, ID_WXSTATICTEXT1, _("Giocatori"), wxPoint(362, 219), wxDefaultSize, 0, _("WxStaticText1"));
	WxFlexGridSizer1->Add(WxStaticText1, 0, wxALIGN_CENTER | wxALL, 5);

	WxButton2 = new wxButton(this, ID_WXBUTTON2, _("Ascolta"), wxPoint(108, 287), wxSize(75, 25), 0, wxDefaultValidator, _("WxButton2"));
	WxFlexGridSizer1->Add(WxButton2, 0, wxALIGN_CENTER | wxALL, 5);

	wxArrayString arrayStringFor_WxListBox1;
	WxListBox1 = new wxListBox(this, ID_WXLISTBOX1, wxPoint(328, 251), wxSize(121, 97), arrayStringFor_WxListBox1, wxLB_SINGLE);
	WxFlexGridSizer1->Add(WxListBox1, 0, wxALIGN_CENTER | wxALL, 5);

	WxStaticText2 = new wxStaticText(this, ID_WXSTATICTEXT2, _("WxStaticText2"), wxPoint(107, 358), wxDefaultSize, 0, _("WxStaticText2"));
	WxFlexGridSizer1->Add(WxStaticText2, 0, wxALIGN_CENTER | wxALL, 5);

	WxEdit1 = new wxTextCtrl(this, ID_WXEDIT1, _("WxEdit1"), wxPoint(328, 358), wxSize(121, 19), 0, wxDefaultValidator, _("WxEdit1"));
	WxFlexGridSizer1->Add(WxEdit1, 0, wxALIGN_CENTER | wxALL, 5);

	SetTitle(_("Tombola"));
	SetIcon(wxNullIcon);
	
	Layout();
	GetSizer()->Fit(this);
	GetSizer()->SetSizeHints(this);
	Center();
	
	////GUI Items Creation End
	
	WxEdit1->SetValue(_("127.0.0.1"));
	
	for (int i=0; i<90; i++) Urna[i] = i+1;
	srand(time(NULL));
	int caso, tmp;
	for (int i=89; i>1; i--) {
        caso = rand()%i;
        tmp = Urna[caso];
        Urna[caso] = Urna[i];
        Urna[i] = tmp;
    }
    NrDentro=90;
    for (int i=0; i<18; i++) punteggi[i]=0;
    prossVinc=0;
    
    // ogni numero nella cartella occupa due posizioni
    // una casella vuota sulla cartella viene indicata con due punti.
    cartella[0] = _(".6..2330..51..78....17..3941..60..85..1925..4358....89");
    cartella[1] = _(".2..20..42..6874...3..29..4453..76....15..34..5569..80");
    cartella[2] = _(".5..22..48..63..81..12..36..54..7586.8..24....5664..90");
    cartella[3] = _(".7..21..45..6172...913..32..57..73....18..3547..65..88");
    cartella[4] = _("..11..3746....7082.4..2638..59..77....1428..49..66..87");
    cartella[5] = _("..10..31..50..7183.1..27..40..6279....16..33..5267..84");
    cartella[6] = _("..1323..4055..70...7..2534..59..73....15..3646..64..87");
    cartella[7] = _("..11..31..5062..82.1..28..4254..78....18..3345..6579..");
    cartella[8] = _("..19..32..5160..86.4..24..47..6372...6..26..49..697288");
    cartella[9] = _("..10..35..56..7680.8..21..44..66..81..14..38..5867..83");
    cartella[10] = _("..1220..43..61..85.216..37..53..74...9..29..48....7790");
    cartella[11] = _("..17..30..5268..84.3..22..41....7189.5..2739..57..75..");
    cartella[12] = _("..10..3543..63..82.316..38..51..73....1724..4556..79..");
    cartella[13] = _(".5..2630..53..74...7..28..48..68..84..14..34..55..7589");
    cartella[14] = _("..11..31..57..7186.2..20..46..6272...6....32..5869..88");
    cartella[15] = _(".4..22..4054..77...9..25..42..60..80..12..39..5967..83");
    cartella[16] = _("..1523..41..61..81.8..2736..52..76....18..3747..66..90");
    cartella[17] = _("..1321..44..6470....19..33..50..7885.1..29..49..65..87");
    cartella[18] = _(".1..20..4655..72....10..3149..60..82..182737..50....90");
    cartella[19] = _(".2..22..40..61..83..12..33..54..7189.4..25..45..6678..");
    cartella[20] = _(".5..2332..53..73....1329..42..63..87.917..38..57..76..");
    cartella[21] = _("..16....445265..80.6..28....58..7484..19..3547..69..86");
    cartella[22] = _(".8..26..43..64..81..14..34..51..7085..15..3948..6779..");
    cartella[23] = _(".3..2136..56....88.7..24..41..6275....11..30..506877..");

    nrClient=0;
}

void TombolaFrm::OnClose(wxCloseEvent& event)
{
    Destroy();	
}


void Tabellone(wxDC &dc) {
    dc.SetPen(wxPen(*wxBLACK, 2, wxSOLID));
    dc.SetBrush(wxBrush(*wxGREEN, wxSOLID));
    int x, y, num;
    wxString numS;
    for (y=10, num=1; y< 180; y+=20) {
      for (x=10; x<200; x+=20, num++) {
        numS.Printf(_("%d"), num);
        dc.DrawText(numS, x, y);
      }
    }
}
/*
 * TombolaFrmPaint
 */
void TombolaFrm::TombolaFrmPaint(wxPaintEvent& event)
{
    // insert your code here
    wxClientDC dc( WxPanel1 );
    Tabellone(dc);
}

/*
 * WxButton1Click
 */
void TombolaFrm::WxButton1Click(wxCommandEvent& event)
{
    // insert your code here
    if (NrDentro<1) return;
    int caso, x, y, riga;
    wxString numS;
    caso = Urna[--NrDentro];
    y = (caso-1)/10;
    x = (caso-1)%10;
    wxClientDC dc( WxPanel1 );
    dc.SetPen(wxPen(*wxBLACK, 2, wxSOLID));
    dc.SetBrush(wxBrush(*wxGREEN, wxSOLID));

    dc.DrawCircle(x*20+15, y*20+15, 10);
    numS.Printf(_("%d"), caso);
    
    dc.DrawText(numS, x*20+10, y*20+10);
    // se il numero è di una cifra il client non può capirlo.
    if (caso<9) numS.Printf(_(".%d"), caso);
    for(int i=1; i<=nrClient; i++) client[i]->Write(numS, numS.Len());
    // controlla punteggio
    riga = (caso-1) / 5;
    ++punteggi[riga];
    bool invia=false;
    if (punteggi[riga]==2 && prossVinc==0) {
        WxMemo1->AppendText(_("\nAmbo"));
        prossVinc++;
        invia=true;
    }
    if (punteggi[riga]==3 && prossVinc==1) {
        WxMemo1->AppendText(_("\nTerno"));
        prossVinc++;
        invia=true;
    }
    if (punteggi[riga]==4 && prossVinc==2) {
        WxMemo1->AppendText(_("\nQuaterna"));
        prossVinc++;
        invia=true;
    }
    if (punteggi[riga]==5 && prossVinc==3) {
        WxMemo1->AppendText(_("\nCinquina"));
        prossVinc++;
        invia=true;
    }
    if (prossVinc==4) {
        for(int i=0; i<18; i+=3)
          if ((punteggi[i]+punteggi[i+1]+punteggi[i+2])==15) {
            WxMemo1->AppendText(_("\nTombola"));
            // fermare il gioco e proporre nuova partita
          }
    }
    if (invia) for(int i=1; i<=nrClient; i++) client[i]->Write(_("91"), 2);
}

/*
 * WxButton2Click
 */
void TombolaFrm::WxButton2Click(wxCommandEvent& event)
{
    // insert your code here
    wxIPV4address indirizzo, ipServer;
    wxString ind = WxEdit1->GetValue();
    indirizzo.Service(3000);
    indirizzo.Hostname(ind);
    server = new wxSocketServer(indirizzo);
    if (!server->Ok()) {
      WxMemo1->AppendText(_("\nErrore: porta occupata"));
      return;
    }

    server->SetEventHandler(*this, SERVER_ID);
    server->SetNotify(wxSOCKET_CONNECTION_FLAG);
    server->Notify(true);
    
    WxButton2->Enable(false);
    
    if ( !server->GetLocal(ipServer) ) {
      WxStaticText2->SetLabel(_("ERRORE"));
    }
    else {
      wxString msg;
      msg.Printf(_("Server in Ascolto %s:%u"), ipServer.IPAddress(), ipServer.Service());
      WxStaticText2->SetLabel(msg);
    }
}

void TombolaFrm::OnServerEvent(wxSocketEvent& event) {
    switch(event.GetSocketEvent()) {
        case wxSOCKET_CONNECTION: {
          nrClient++;
          client[nrClient] = server->Accept(false);
          WxMemo1->AppendText(_("\nAccettata connessione da:"));

          wxIPV4address ipClient;
          client[nrClient]->GetPeer(ipClient);
          wxString ipV4Client = ipClient.IPAddress();
          WxListBox1->InsertItems(1, &ipV4Client, 0);
          WxStaticText2->SetLabel(ipV4Client);
          client[nrClient]->SetEventHandler(*this, SOCKET_ID);
          client[nrClient]->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG | wxSOCKET_CONNECTION_FLAG);
          client[nrClient]->Notify(true);
          client[nrClient]->Write(cartella[nrClient-1], cartella[nrClient-1].Len());
        }
    }
}

void TombolaFrm::OnSocketEvent(wxSocketEvent& event) {
    client[0] = event.GetSocket();
    switch(event.GetSocketEvent()) {
        case wxSOCKET_INPUT: {
            char buf[100];
            client[0]->Read(buf, sizeof(buf));
            wxIPV4address ipClient;
            client[0]->GetPeer(ipClient);
            wxString ipV4Client = ipClient.IPAddress();
            WxMemo1->AppendText(_("\nMessaggio da: ") + ipV4Client + _("\n") + _(buf));
            break;
        }
        case wxSOCKET_LOST: {
            wxIPV4address ipClient;
            client[0]->GetPeer(ipClient);
            wxString ipV4Client = ipClient.IPAddress();
            WxMemo1->AppendText(_("\nClient: ") + ipV4Client + _(" scollegato\n"));
            
            for (int i=1; i<=nrClient; i++) {
              client[i]->GetPeer(ipClient);
              wxString ClientScon = ipClient.IPAddress();
              if(ClientScon.IsSameAs(ipV4Client)){
                WxMemo1->AppendText(_("\nElimino socket verso: ") + ipV4Client + _("\n"));
                client[i]->Destroy();
                client[i]=client[nrClient];
                break;
              }
            }
            nrClient--;
            break;
        }
    }
}

L'applicazione Client.

Avviare un nuovo progetto wxDev-C++ basato su wxWidgets Frame e denominarlo ClientTombola.

sul form sono collocati:

il file ClientTombolaFrm.h


///-----------------------------------------------------------------
///
/// @file      ClientTombolaFrm.h
/// @author    Pc
/// Created:   26/11/2013 18:55:42
/// @section   DESCRIPTION
///            ClientTombolaFrm class declaration
///
///------------------------------------------------------------------

#ifndef __CLIENTTOMBOLAFRM_H__
#define __CLIENTTOMBOLAFRM_H__

#ifdef __BORLANDC__
	#pragma hdrstop
#endif

#ifndef WX_PRECOMP
	#include <wx/wx.h>
	#include <wx/frame.h>
#else
	#include <wx/wxprec.h>
#endif

//Do not add custom headers between 
//Header Include Start and Header Include End.
//wxDev-C++ designer will remove them. Add custom headers after the block.
////Header Include Start
#include <wx/panel.h>
#include <wx/textctrl.h>
#include <wx/button.h>
#include <wx/sizer.h>
////Header Include End

////Dialog Style Start
#undef ClientTombolaFrm_STYLE
#define ClientTombolaFrm_STYLE wxCAPTION | wxSYSTEM_MENU | wxMINIMIZE_BOX | wxCLOSE_BOX
////Dialog Style End
#include <wx/socket.h>
class ClientTombolaFrm : public wxFrame
{
    private:
        wxSocketClient *client;
        wxSocketBase *socket;
        wxIPV4address *indirizzo;
        char buf[55];
        int valore[27];
        int puntiRiga[3];
        int prossPunto;
        bool primoPack;
	private:
		DECLARE_EVENT_TABLE();
		
	public:
		ClientTombolaFrm(wxWindow *parent, wxWindowID id = 1, const wxString &title = wxT("ClientTombola"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = ClientTombolaFrm_STYLE);
		virtual ~ClientTombolaFrm();
		void OnSocketEvent(wxSocketEvent& event);
		void WxButton1Click(wxCommandEvent& event);
		void WxPanel1UpdateUI(wxUpdateUIEvent& event);
		void WxButton2Click(wxCommandEvent& event);

	private:
		//Do not add custom control declarations between
		//GUI Control Declaration Start and GUI Control Declaration End.
		//wxDev-C++ will remove them. Add custom code after the block.
		////GUI Control Declaration Start
		wxButton *WxButton2;
		wxTextCtrl *WxEdit1;
		wxPanel *WxPanel1;
		wxTextCtrl *WxMemo1;
		wxButton *WxButton1;
		wxBoxSizer *WxBoxSizer1;
		////GUI Control Declaration End
	private:
		//Note: if you receive any error with these enum IDs, then you need to
		//change your old form code that are based on the #define control IDs.
		//#defines may replace a numeric value for the enum names.
		//Try copy and pasting the below block in your old form header files.
		enum
		{
			////GUI Enum Control ID Start
			ID_WXBUTTON2 = 1007,
			ID_WXEDIT1 = 1006,
			ID_WXPANEL1 = 1005,
			ID_WXMEMO1 = 1004,
			ID_WXBUTTON1 = 1003,
			////GUI Enum Control ID End
			SOCKET_ID,
			ID_DUMMY_VALUE_ //don't remove this value unless you have other enum values
		};
		
	private:
		void OnClose(wxCloseEvent& event);
		void CreateGUIControls();
		void Cartella(wxDC &dc);
		void Disegna();
		void Controlla(int);
};

#endif

il file ClientTombolaFrm.cpp


///-----------------------------------------------------------------
///
/// @file      ClientTombolaFrm.cpp
/// @author    Pc
/// Created:   26/11/2013 18:55:42
/// @section   DESCRIPTION
///            ClientTombolaFrm class implementation
///
///------------------------------------------------------------------

#include "ClientTombolaFrm.h"

//Do not add custom headers between
//Header Include Start and Header Include End
//wxDev-C++ designer will remove them
////Header Include Start
////Header Include End

//----------------------------------------------------------------------------
// ClientTombolaFrm
//----------------------------------------------------------------------------
//Add Custom Events only in the appropriate block.
//Code added in other places will be removed by wxDev-C++
////Event Table Start
BEGIN_EVENT_TABLE(ClientTombolaFrm,wxFrame)
	////Manual Code Start
	EVT_SOCKET(SOCKET_ID, ClientTombolaFrm::OnSocketEvent)
	////Manual Code End
	
	EVT_CLOSE(ClientTombolaFrm::OnClose)
	EVT_BUTTON(ID_WXBUTTON2,ClientTombolaFrm::WxButton2Click)
	
	EVT_UPDATE_UI(ID_WXPANEL1,ClientTombolaFrm::WxPanel1UpdateUI)
	EVT_BUTTON(ID_WXBUTTON1,ClientTombolaFrm::WxButton1Click)
END_EVENT_TABLE()
////Event Table End

ClientTombolaFrm::ClientTombolaFrm(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
: wxFrame(parent, id, title, position, size, style)
{
	CreateGUIControls();
}

ClientTombolaFrm::~ClientTombolaFrm()
{
}

void ClientTombolaFrm::CreateGUIControls()
{
	//Do not add custom code between
	//GUI Items Creation Start and GUI Items Creation End
	//wxDev-C++ designer will remove them.
	//Add the custom code before or after the blocks
	////GUI Items Creation Start

	WxBoxSizer1 = new wxBoxSizer(wxVERTICAL);
	this->SetSizer(WxBoxSizer1);
	this->SetAutoLayout(true);

	WxButton1 = new wxButton(this, ID_WXBUTTON1, _("Chiedi Cartella"), wxPoint(120, 5), wxSize(139, 25), 0, wxDefaultValidator, _("WxButton1"));
	WxBoxSizer1->Add(WxButton1, 0, wxALIGN_CENTER | wxALL, 5);

	WxMemo1 = new wxTextCtrl(this, ID_WXMEMO1, wxEmptyString, wxPoint(5, 40), wxSize(369, 89), wxTE_MULTILINE, wxDefaultValidator, _("WxMemo1"));
	WxMemo1->SetMaxLength(0);
	WxMemo1->AppendText(_("WxMemo1"));
	WxMemo1->SetFocus();
	WxMemo1->SetInsertionPointEnd();
	WxBoxSizer1->Add(WxMemo1, 0, wxALIGN_CENTER | wxALL, 5);

	WxPanel1 = new wxPanel(this, ID_WXPANEL1, wxPoint(25, 139), wxSize(329, 145));
	WxBoxSizer1->Add(WxPanel1, 0, wxALIGN_CENTER | wxALL, 5);

	WxEdit1 = new wxTextCtrl(this, ID_WXEDIT1, _("WxEdit1"), wxPoint(129, 294), wxSize(121, 19), 0, wxDefaultValidator, _("WxEdit1"));
	WxBoxSizer1->Add(WxEdit1, 0, wxALIGN_CENTER | wxALL, 5);

	WxButton2 = new wxButton(this, ID_WXBUTTON2, _("Connetti"), wxPoint(152, 323), wxSize(75, 25), 0, wxDefaultValidator, _("WxButton2"));
	WxBoxSizer1->Add(WxButton2, 0, wxALIGN_CENTER | wxALL, 5);

	SetTitle(_("ClientTombola"));
	SetIcon(wxNullIcon);
	
	Layout();
	GetSizer()->Fit(this);
	GetSizer()->SetSizeHints(this);
	Center();
	
	////GUI Items Creation End

	WxEdit1->SetValue(_("127.0.0.1"));
	primoPack = true;
	puntiRiga[0]=puntiRiga[1]=puntiRiga[2]=0;
	prossPunto=2;
}

void ClientTombolaFrm::OnClose(wxCloseEvent& event)
{
	Destroy();
}

/*
 * WxButton1Click
 */
void ClientTombolaFrm::WxButton1Click(wxCommandEvent& event)
{
	// insert your code here
	client->Connect(*indirizzo, false);
}

void ClientTombolaFrm::OnSocketEvent(wxSocketEvent& event) {
  socket = event.GetSocket();

  switch(event.GetSocketEvent()) {
    case wxSOCKET_CONNECTION: {
      break;
    }
    case wxSOCKET_INPUT: {
      if (primoPack) {
        socket->Read(buf, 54);
        buf[54]=0x0;
        Disegna();
        primoPack=false;
      } else {
        socket->Read(buf, 2);
        wxString num;
        if (buf[0]=='.' && buf[1]!='.') num = _(buf[1]);
        // numero di due cifre
        if (buf[0]!='.' && buf[1]!='.') num = _(buf[0])+_(buf[1]);
        // stampa se formato da una o due cifre
        // se non è un numero memorizza 0 (=casella vuota)
        if (buf[0]=='.' && buf[1]=='.') num = _('0');

        WxMemo1->AppendText(_("\nEstratto: ") + num);
        wxString msg;
        // con 91 il server comunica che è stata realizzata una combinazione vincente
        if (wxAtoi(num)==91) {
          switch(prossPunto) {
            case 2: 
              msg = _("Ambo");
              break;
            case 3:
              msg = _("Terno");
              break;
            case 4:
              msg = _("Quaterna");
              break;
            case 5:
              msg = _("Cinquina");
              break;
            case 6:
              msg = _("Tombola");
          }
          WxMemo1->AppendText(_("\nFatto: ") + msg);
          prossPunto++;
        }
        Controlla(wxAtoi(num));
      }
      break;
    }
    case wxSOCKET_LOST: {
      socket->Destroy();
      break;
    }
  }
}

void ClientTombolaFrm::Controlla(int k){
    int posX, posY, riga;
    for (int i=0; i<27; i++)
      if(valore[i]==k) {
        posY = (i/9)*20+25;
        posX = (i%9)*20+25;
        wxClientDC dc(WxPanel1);
        dc.SetPen(wxPen(*wxBLACK, 2, wxSOLID));
        dc.SetBrush(wxBrush(*wxGREEN, wxSOLID));
        dc.DrawCircle(posX, posY, 10);
        wxString msg;
        msg.Printf("%d",k);
        dc.DrawText(msg, posX-5, posY-5);
        
        // controlla punto
        puntiRiga[riga=i/9]++;
        if (puntiRiga[riga]==prossPunto) {
          switch(prossPunto) {
            case 2: 
              msg = _("Ambo");
              break;
            case 3:
              msg = _("Terno");
              break;
            case 4:
              msg = _("Quaterna");
              break;
            case 5:
              msg = _("Cinquina");
              break;
            case 6:
              msg = _("Tombola");
          }
          WxMemo1->AppendText(_("\nPunto: ") + msg);

          client->Write(_("punto" + msg),10);
        }
        if (puntiRiga[0]+puntiRiga[1]+puntiRiga[2]==15) {
          WxMemo1->AppendText(_("\nTombola"));
          client->Write(_("Tombola"),7);
        }
        break;
      }
}

void ClientTombolaFrm::Disegna(){
    wxClientDC dc(WxPanel1);
    dc.SetPen(wxPen(*wxBLACK, 2, wxSOLID));
    dc.SetBrush(wxBrush(*wxGREEN, wxSOLID));
    wxString num;
    int posX, posY;
    posX=0;
    posY=20;
    for (int j=0; j<54; j+=2) {
      posX += 20;
      if(posX==200) {
        posX = 20;
        posY = posY+=20;
      }
      // numero di una sola cifra
      if (buf[j]=='.' && buf[j+1]!='.') num = _(buf[j+1]);
      
      // numero di due cifre
      if (buf[j]!='.' && buf[j+1]!='.') num = _(buf[j])+_(buf[j+1]);
  
      // stampa se formato da una o due cifre
      if (buf[j+1]!='.') dc.DrawText(num, posX, posY);

      // se non è un numero memorizza 0 (=casella vuota)
      if (buf[j]=='.' && buf[j+1]=='.') num = _('0');

      valore[j/2] = wxAtoi(num);
    }
}
void ClientTombolaFrm::Cartella(wxDC &dc) {
    dc.SetPen(wxPen(*wxBLACK, 2, wxSOLID));
    dc.SetBrush(wxBrush(*wxGREEN, wxSOLID));
    dc.DrawLine(15,18, 200,18);
    dc.DrawLine(15,38, 200,38);
    dc.DrawLine(15,58, 200,58);
    dc.DrawLine(15,78, 200,78);
    
    dc.DrawLine(15,18, 15,78);
    dc.DrawLine(35,18, 35,78);
    dc.DrawLine(55,18, 55,78);
    dc.DrawLine(75,18, 75,78);
    dc.DrawLine(95,18, 95,78);
    dc.DrawLine(115,18, 115,78);
    dc.DrawLine(135,18, 135,78);
    dc.DrawLine(155,18, 155,78);
    dc.DrawLine(175,18, 175,78);
    dc.DrawLine(200,18, 200,78);
}
/*
 * WxPanel1UpdateUI
 */
void ClientTombolaFrm::WxPanel1UpdateUI(wxUpdateUIEvent& event)
{
	// insert your code here
	wxClientDC dc(WxPanel1);
	Cartella(dc);
}

/*
 * WxButton2Click
 */
void ClientTombolaFrm::WxButton2Click(wxCommandEvent& event)
{
	// insert your code here
	indirizzo = new wxIPV4address();
	wxString ind = WxEdit1->GetValue();
	indirizzo->Hostname(ind);
	indirizzo->Service(3000);
	client = new wxSocketClient();
	client->SetEventHandler(*this, SOCKET_ID);
	client->SetNotify(wxSOCKET_CONNECTION_FLAG | wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
	client->Notify(true);
}

Esercizi

Il server possiede 24 cartelle. Non controlla l'esaurimento delle cartelle disponibili. Non controlla nemmeno il superamento del numero di connessioni.

Un client deve avere la possibilità di comunicare una combinazione vincente.