2 years ago

#54001

test-img

Ruud

Input Available Logs in wxWidgets socket example with for-loop in Client.cpp OnTest2 function

I am beginning to learn about sockets in wxWidgets, and run on Windows 10 (latest version), CodeBlocks 20.03 with mingw2 (gnu 11.2), and wxWidgets 3.15.
The socket sample compiles and run OK.
Because I will be sending many wxStrings (up to 7000 in one session) from the client to the server, I added a for-loop in the client.cpp OnTest2 function (see below).

Where the single transfer of the original socket sample runs OK every time, the adapted client.cpp OnTest2 function always logs Input-Available events at various locations.
For some reason "Input-Available" is logged on all sends.
The Server receives everything, so I am not worried that much about the future content.

Still, these Input-Available Log messages should not happen, I think. I read somewhere that calling wxThread::Yield() prior to calling WaitForRead() would help, but it did not.

Is something wrong in my "simple" approach of adding a for-loop?
I hope someone can help me understand why these Input-Available log message appear, and help me find a solution.

Edit: I have reduced the wxWidgets socket examples to the smallest of my 'beginners' abilities.

minclient.cpp

#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#  include "wx/wx.h"
#endif

#include "wx/socket.h"
#include "wx/sstream.h"

class MyApp : public wxApp
{
    public:
        virtual bool OnInit() wxOVERRIDE;
};

class MyFrame : public wxFrame
{
    public:
        MyFrame();
        ~MyFrame();

        void OnQuit(wxCommandEvent& event);
        void OnOpenConnection(wxCommandEvent& event);
        void OnCloseConnection(wxCommandEvent& event);
        void OpenConnection(wxSockAddress::Family family);
        void OnSocketEvent(wxSocketEvent& event);
        void OnTest(wxCommandEvent& event);

    private:
        wxSocketClient *m_sock;
        wxMenu         *m_menuFile;
        wxMenu         *m_menuSocket;
        wxMenuBar      *m_menuBar;

    wxDECLARE_EVENT_TABLE();
};

enum
{
    CLIENT_QUIT = wxID_EXIT,
    CLIENT_ABOUT = wxID_ABOUT,
    CLIENT_OPEN = 100,
    CLIENT_TEST,
    CLIENT_CLOSE,
    SOCKET_ID
};

wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_MENU(CLIENT_QUIT,  MyFrame::OnQuit)
    EVT_MENU(CLIENT_OPEN,  MyFrame::OnOpenConnection)
    EVT_MENU(CLIENT_TEST,  MyFrame::OnTest)
    EVT_MENU(CLIENT_CLOSE, MyFrame::OnCloseConnection)
    EVT_SOCKET(SOCKET_ID,  MyFrame::OnSocketEvent)
wxEND_EVENT_TABLE()

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit()
{
    if ( !wxApp::OnInit() )
        return false;

    MyFrame *frame = new MyFrame();
    frame->Show(true);

    return true;
}

MyFrame::MyFrame() : wxFrame((wxFrame *)NULL, wxID_ANY,
                             _("wxSocket demo: Client"),
                             wxDefaultPosition, wxSize(300, 200))
{
    m_menuFile = new wxMenu();
    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"));
    m_menuSocket->AppendSeparator();
    m_menuSocket->Append(CLIENT_TEST, _("Test &2\tCtrl-F2"), _("Test ReadMsg and WriteMsg"));
    m_menuSocket->AppendSeparator();
    m_menuSocket->Append(CLIENT_CLOSE, _("&Close session\tCtrl-C"), _("Close connection"));

    m_menuBar = new wxMenuBar();
    m_menuBar->Append(m_menuFile, _("&File"));
    m_menuBar->Append(m_menuSocket, _("&TCP"));

    SetMenuBar(m_menuBar);

    m_sock = new wxSocketClient();
    m_sock->SetEventHandler(*this, SOCKET_ID);
    m_sock->SetNotify(wxSOCKET_CONNECTION_FLAG | wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
    m_sock->Notify(true);
}

MyFrame::~MyFrame()
{
    delete m_sock;
}

void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
    Close(true);
}

void MyFrame::OnOpenConnection(wxCommandEvent& WXUNUSED(event))
{
    OpenConnection(wxSockAddress::IPV4);
}

void MyFrame::OpenConnection(wxSockAddress::Family family)
{
    wxIPaddress * addr;
    wxIPV4address addr4;
    addr = &addr4;

    m_menuSocket->Enable(CLIENT_OPEN, false);
    m_menuSocket->Enable(CLIENT_CLOSE, false);

    wxString hostname = "localhost";
    addr->Hostname(hostname);
    addr->Service(3000);

    m_sock->Connect(*addr, false);
}

void MyFrame::OnCloseConnection(wxCommandEvent& WXUNUSED(event))
{
    m_sock->Close();
}

void MyFrame::OnSocketEvent(wxSocketEvent& event)
{
    switch ( event.GetSocketEvent() )
    {
        case wxSOCKET_INPUT:
            std::cout << "Input available on the socket.\n";
            break;
        case wxSOCKET_LOST:
            std::cout << "Socket connection was unexpectedly lost.\n";
            break;
        case wxSOCKET_CONNECTION:
            std::cout << "... socket is now connected.\n";
            break;
        default:
            std::cout << "Unknown socket event!\n";
            break;
    }
}

void MyFrame::OnTest(wxCommandEvent& WXUNUSED(event))
{
    for(int f = 0; f < 2; f++)
    {
        unsigned char c = 0xCE;
        m_sock->Write(&c, 1);

        m_sock->SetFlags(wxSOCKET_WAITALL);

        wxString s = "This is my string to send";
        const wxScopedCharBuffer msg1(s.utf8_str());
        size_t len  = wxStrlen(msg1) + 1;
        wxCharBuffer msg2(wxStrlen(msg1));

        m_sock->WriteMsg(msg1, len);
        if(m_sock->Error())
            { std::cout << " Write failed !\n"; }

        m_sock->WaitForRead(2);

        if (m_sock->IsData())
        {
            m_sock->ReadMsg(msg2.data(), len);
            if(m_sock->Error())
                { std::cout << " Read failed !\n"; }
            else
            {
                if (memcmp(msg1, msg2, len) != 0)
                { std::cout << "Test failed !\n"; }
                else
                { std::cout << "Returned msg: \"" << msg2 << "\"" << std::endl; }
            }
        }
        else
        { std::cout << "Timeout ! Test failed.\n"; }
    }
}

minserver.cpp

#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#  include "wx/wx.h"
#endif

#include "wx/socket.h"

typedef wxIPV4address IPaddress;

class MyApp : public wxApp
{
    public:
        virtual bool OnInit() wxOVERRIDE;
};

class MyFrame : public wxFrame
{
    public:
        MyFrame();
        ~MyFrame();

        void OnQuit(wxCommandEvent& event);
        void OnServerEvent(wxSocketEvent& event);
        void OnSocketEvent(wxSocketEvent& event);

        void Test(wxSocketBase *sock);

    private:
        wxSocketServer *m_server;
        wxMenu *m_menuFile;
        wxMenuBar *m_menuBar;
        int m_numClients;

    wxDECLARE_EVENT_TABLE();
};

enum
{
    SERVER_QUIT = wxID_EXIT,
    SERVER_ID = 100,
    SOCKET_ID
};

wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_MENU(SERVER_QUIT,  MyFrame::OnQuit)
    EVT_SOCKET(SERVER_ID,  MyFrame::OnServerEvent)
    EVT_SOCKET(SOCKET_ID,  MyFrame::OnSocketEvent)
wxEND_EVENT_TABLE()

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit()
{
    if ( !wxApp::OnInit() )
        return false;

    MyFrame *frame = new MyFrame();
    frame->Show(true);

    return true;
}

MyFrame::MyFrame() : wxFrame((wxFrame *)NULL, wxID_ANY,
                             _("wxSocket demo: Server"),
                             wxDefaultPosition, wxSize(300, 200))
{
    m_menuFile = new wxMenu();
    m_menuFile->Append(SERVER_QUIT, _("E&xit\tAlt-X"), _("Quit server"));

    m_menuBar = new wxMenuBar();
    m_menuBar->Append(m_menuFile, _("&File"));
    SetMenuBar(m_menuBar);

    IPaddress addr;
    addr.Service(3000);

    m_server = new wxSocketServer(addr);
    if (! m_server->IsOk())
    {
        std::cout << "Could not listen at the specified port !\n";
        return;
    }

    IPaddress addrReal;
    if ( !m_server->GetLocal(addrReal) )
    { std::cout << "ERROR: couldn't get the address we bound to.\n"; }
    else
    { std::cout << "Server listening at " << addrReal.IPAddress() << ": " << addrReal.Service() << std::endl; }

    m_server->SetEventHandler(*this, SERVER_ID);
    m_server->SetNotify(wxSOCKET_CONNECTION_FLAG);
    m_server->Notify(true);

    m_numClients = 0;
}

MyFrame::~MyFrame()
{
    delete m_server;
}

void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
    Close(true);
}

void MyFrame::OnServerEvent(wxSocketEvent& event)
{
    wxString s = "OnServerEvent: ";
    wxSocketBase *sock;

    switch(event.GetSocketEvent())
    {
        case wxSOCKET_CONNECTION:
            s.Append("wxSOCKET_CONNECTION");
            break;
        default:
            s.Append("Unexpected event !");
            break;
    }
    std::cout << s << std::endl;

    sock = m_server->Accept(false);
    if (sock)
    {
        IPaddress addr;
        if ( !sock->GetPeer(addr) )
        { std::cout << "New connection from unknown client accepted.\n"; }
        else
        { std::cout << "New client connection from " << addr.IPAddress() << ":" << addr.Service() << " accepted\n"; }
    }
    else
    {
        std::cout << "Error: couldn't accept a new connection\n";
        return;
    }

    sock->SetEventHandler(*this, SOCKET_ID);
    sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
    sock->Notify(true);

    m_numClients++;
}

void MyFrame::OnSocketEvent(wxSocketEvent& event)
{
    wxString s = "OnSocketEvent: ";
    wxSocketBase *sock = event.GetSocket();

    switch(event.GetSocketEvent())
    {
        case wxSOCKET_INPUT:
            s.Append(_("wxSOCKET_INPUT"));
            break;
        case wxSOCKET_LOST:
            s.Append(_("wxSOCKET_LOST"));
            break;
        default:
            s.Append(_("Unexpected event !"));
            break;
    }
    std::cout << s << std::endl;

    switch(event.GetSocketEvent())
    {
        case wxSOCKET_INPUT:
        {
            sock->SetNotify(wxSOCKET_LOST_FLAG);

            unsigned char c;
            sock->Read(&c, 1);

            switch (c)
            {
                case 0xCE:
                    Test(sock);
                    break;
                default:
                std::cout << "Unknown test id received from client\n";
            }
            sock->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);
            break;
        }
        case wxSOCKET_LOST:
        {
            m_numClients--;
            std::cout << "Deleting socket.\n";
            sock->Destroy();
            break;
        }
        default: ;
    }
}

void MyFrame::Test(wxSocketBase *sock)
{
    char buf[4096];

    wxUint32 len = sock->ReadMsg(buf, sizeof(buf)).LastCount();
    if ( !len )
    {
      std::cout << "Failed to read message.\n";
      return;
    }
    std::cout << "Received: \"" << wxString::FromUTF8(buf, len) << "\" , Returning it\n";

    sock->WriteMsg(buf, len);
}

The below message on the client happens at every 'test'. (Also when the for loop is removed.)

Input available on the socket

I searched for socket libraries, and found only 8 sort of current ones. (Boos.ASIO, beej, bestofcpp, netlib, and others) They were either to complicated for me to start with, or had python dependency. I appreciate suggestions for easy to learn alternative libraries.

c++

windows

mingw

wxwidgets

0 Answers

Your Answer

Accepted video resources