There is a bug reported for the same problem. I have over come this issue by setting the flags of the client to wxSOCKET_BLOCK| wxSOCKET_NOWAIT.
After resolving this I am facing a new problem related to threads and sockets.
I am creating two client sockets on client.cpp's main thread. I continuously peek on the second socket for any data. If I block the main thread using wxCondition, the secondary thread also blocks on the socket. The data written on the second client from the the server, it doesn't reach the client.
Code: Select all
/////////////////////////////////////////////////////////////////////////////
// Name: client.cpp
// Purpose: Client for wxSocket demo
// Author: Guillermo Rodriguez Garcia <[email protected]>
// Modified by:
// Created: 1999/09/19
// RCS-ID: $Id: client.cpp 35650 2005-09-23 12:56:45Z MR $
// Copyright: (c) 1999 Guillermo Rodriguez Garcia
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ==========================================================================
// declarations
// ==========================================================================
// --------------------------------------------------------------------------
// headers
// --------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
# pragma hdrstop
#endif
// for all others, include the necessary headers
#ifndef WX_PRECOMP
# include "wx/wx.h"
#endif
#include "wx/socket.h"
#include "wx/url.h"
#include "wx/wfstream.h"
#include <stdio.h>
// --------------------------------------------------------------------------
// resources
// --------------------------------------------------------------------------
// the application icon
#if defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__) || defined(__WXMAC__)
# include "mondrian.xpm"
#endif
// --------------------------------------------------------------------------
// classes
// --------------------------------------------------------------------------
// Define a new application type
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
// Define a new frame type: this is going 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 OnCloseConnection(wxCommandEvent& event);
// 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;
wxSocketClient *m_sock2;
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()
};
class clientThread :wxThread
{
public:
wxTextCtrl *m_text2;
MyFrame *frame;
wxSocketClient *m_sock;
clientThread( wxTextCtrl *m_text,wxSocketClient *m_sock2,MyFrame *obj):wxThread(wxTHREAD_JOINABLE)
{
frame = obj;
m_sock = m_sock2;
m_text2 =m_text;
}
/*thread execution starts here*/
virtual void *Entry(void);
void create(void);
};
// --------------------------------------------------------------------------
// constants
// --------------------------------------------------------------------------
// IDs for the controls and the menu commands
enum
{
// menu items
CLIENT_QUIT = wxID_EXIT,
CLIENT_ABOUT = wxID_ABOUT,
CLIENT_OPEN = 100,
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 for wxWidgets
// --------------------------------------------------------------------------
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(CLIENT_QUIT, MyFrame::OnQuit)
EVT_MENU(CLIENT_ABOUT, MyFrame::OnAbout)
EVT_MENU(CLIENT_OPEN, MyFrame::OnOpenConnection)
EVT_MENU(CLIENT_TEST1, MyFrame::OnTest1)
EVT_MENU(CLIENT_CLOSE, MyFrame::OnCloseConnection)
EVT_MENU(CLIENT_DGRAM, MyFrame::OnDatagram)
EVT_SOCKET(SOCKET_ID, MyFrame::OnSocketEvent)
END_EVENT_TABLE()
IMPLEMENT_APP(MyApp)
// ==========================================================================
// implementation
// ==========================================================================
// --------------------------------------------------------------------------
// the application class
// --------------------------------------------------------------------------
void *clientThread::Entry(void)
{
unsigned char ulength =0;
const wxChar *buf1;
wxChar *buf2;
unsigned char len;
unsigned char c = 0xBE;
char *buf3;
buf1 = _("Test string (less than 256 chars for socket 2!)");
len = (unsigned char)((wxStrlen(buf1) + 1) * sizeof(wxChar));
buf2 = new wxChar[wxStrlen(buf1) + 1];
m_sock->Write(&c, 1);
// m_text->AppendText(_("\nChar (%d) for socket 2\n"),m_sock2->LastCount());
m_sock->Write(&len, 1);
// m_text->AppendText(_("\nlength sent (%d) for socket 2\n"),m_sock2->LastCount());
m_sock->Write(buf1, len);
m_text2->AppendText(_("\nData sent for socket 2\n"));
while (TRUE)
{
m_text2->AppendText(_("\n Peeking the data\n"));
printf("Peeking the data\n");
// If main thread is blocked, this Peek always returns Zero.
m_sock->Peek(&ulength,1);
printf("Peeking the data: %d",ulength);
if ( ulength == 0)
{
continue;
}
printf("Reading the data: %d",ulength);
// m_text2->AppendText(_("\n Reading the data\n"));
buf3 = new char[ulength];
if ( buf3 != NULL )
{
m_sock->Read(buf3,ulength);
break;
}
printf("%s\n",buf3);
}
}
void clientThread::create(void)
{
// create secondary thread
Create();
Run();
}
bool MyApp::OnInit()
{
// Create the main application window
MyFrame *frame = new MyFrame();
// Show it and tell the application that it's our main window
frame->Show(true);
SetTopWindow(frame);
// success
return true;
}
// --------------------------------------------------------------------------
// main frame
// --------------------------------------------------------------------------
// frame constructor
MyFrame::MyFrame() : wxFrame((wxFrame *)NULL, wxID_ANY,
_("wxSocket demo: Client"),
wxDefaultPosition, wxSize(300, 200))
{
// Give the frame an icon
SetIcon(wxICON(mondrian));
// 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"), _("Connect to server"));
m_menuSocket->AppendSeparator();
m_menuSocket->Append(CLIENT_TEST1, _("Test &1"), _("Test basic functionality"));
m_menuSocket->Append(CLIENT_TEST2, _("Test &2"), _("Test ReadMsg and WriteMsg"));
m_menuSocket->Append(CLIENT_TEST3, _("Test &3"), _("Test large data transfer"));
m_menuSocket->AppendSeparator();
m_menuSocket->Append(CLIENT_CLOSE, _("&Close session"), _("Close connection"));
m_menuDatagramSocket = new wxMenu();
m_menuDatagramSocket->Append(CLIENT_DGRAM, _("Send Datagram"), _("Test UDP sockets"));
#if wxUSE_URL
m_menuProtocols = new wxMenu();
m_menuProtocols->Append(CLIENT_TESTURL, _("Test URL"), _("Get data from the specified URL"));
#endif
// Append menus to the menubar
m_menuBar = new wxMenuBar();
m_menuBar->Append(m_menuFile, _("&File"));
m_menuBar->Append(m_menuSocket, _("&SocketClient"));
m_menuBar->Append(m_menuDatagramSocket, _("&DatagramSocket"));
#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 to wxSocket demo: Client\nClient ready\n"),
wxDefaultPosition, wxDefaultSize,
wxTE_MULTILINE | wxTE_READONLY);
// Create the sockets
m_sock = new wxSocketClient();
m_sock2 = new wxSocketClient();
m_busy = false;
UpdateStatusBar();
}
MyFrame::~MyFrame()
{
// No delayed deletion here, as the frame is dying anyway
delete m_sock;
}
// event handlers
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
Close(true);
}
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxMessageBox(_("wxSocket demo: Client\n(c) 1999 Guillermo Rodriguez Garcia\n"),
_("About Client"),
wxOK | wxICON_INFORMATION, this);
}
void MyFrame::OnOpenConnection(wxCommandEvent& WXUNUSED(event))
{
wxIPV4address addr;
const wxChar *buf1;
wxChar *buf2;
unsigned char len;
m_menuSocket->Enable(CLIENT_OPEN, false);
m_menuSocket->Enable(CLIENT_CLOSE, false);
// Ask user for server address
wxString hostname = wxGetTextFromUser(
_("Enter the address of the wxSocket demo server:"),
_("Connect ..."),
_("localhost"));
addr.Hostname(hostname);
addr.Service(3000);
m_text->AppendText(_("\nTrying to connect (timeout = 10 sec) ...\n"));
m_sock->Connect(addr, false);
m_sock->WaitOnConnect(10);
if (m_sock->IsConnected())
m_text->AppendText(_("Succeeded ! Connection established\n"));
else
{
m_sock->Close();
m_text->AppendText(_("Failed ! Unable to connect\n"));
wxMessageBox(_("Can't connect to the specified host"), _("Alert !"));
}
buf1 = _("Test string (less than 256 chars!)");
len = (unsigned char)((wxStrlen(buf1) + 1) * sizeof(wxChar));
buf2 = new wxChar[wxStrlen(buf1) + 1];
m_text->AppendText(_("Sending a test buffer to the server ..."));
// created Client two for testing
m_sock2->Connect(addr, false);
m_sock2->WaitOnConnect(10);
if (m_sock2->IsConnected())
m_text->AppendText(_("Succeeded ! Connection established\n"));
else
{
m_sock2->Close();
m_text->AppendText(_("Failed ! Unable to connect\n"));
wxMessageBox(_("Can't connect to the specified host"), _("Alert !"));
}
m_sock2->SetTimeout(5);
m_text->AppendText(_("Sending a test buffer to the server ..."));
unsigned char c = 0xBE;
m_sock->Write(&c, 1);
m_sock->Write(&len, 1);
m_sock->Write(buf1, len);
m_text->AppendText(_("\nData sent for socket 1\n"));
// create thread for listening
clientThread *cltThread = new clientThread(m_text,m_sock2,this);
cltThread->create();
UpdateStatusBar();
}
void MyFrame::OnTest1(wxCommandEvent& WXUNUSED(event))
{
wxMutex *pMutexNotify = new wxMutex;
wxCondition *pConditionNotify = new wxCondition(*pMutexNotify);
if ((pMutexNotify->Lock()) != wxMUTEX_NO_ERROR )
{
m_text->AppendText(_("Mutex Error in NOTIFY()"));
}
else
{
m_text->AppendText(_("Mutex SUCCESS in NOTIFY()"));
}
#if 0
unsigned char c = 0xCE;
m_sock->Write(&c, 1);
#endif
if ((pConditionNotify->Wait()) != wxCOND_NO_ERROR)
{
m_text->AppendText(_("Condition Wait Error in NOTIFY()"));
}
else
{
m_text->AppendText(_("Condition Wait SUCCESS in NOTIFY()"));
}
}
void MyFrame::OnCloseConnection(wxCommandEvent& WXUNUSED(event))
{
m_sock->Close();
UpdateStatusBar();
}
void MyFrame::OnDatagram(wxCommandEvent& WXUNUSED(event))
{
m_text->AppendText(_("\n=== Datagram test begins ===\n"));
m_text->AppendText(_("Sorry, not implemented\n"));
m_text->AppendText(_("=== Datagram test ends ===\n"));
}
void MyFrame::OnSocketEvent(wxSocketEvent& event)
{
wxString s = _("OnSocketEvent: ");
switch(event.GetSocketEvent())
{
case wxSOCKET_INPUT : s.Append(_("wxSOCKET_INPUT\n")); break;
case wxSOCKET_LOST : s.Append(_("wxSOCKET_LOST\n")); break;
case wxSOCKET_CONNECTION : s.Append(_("wxSOCKET_CONNECTION\n")); break;
default : s.Append(_("Unexpected event !\n")); break;
}
m_text->AppendText(s);
UpdateStatusBar();
}
// convenience functions
void MyFrame::UpdateStatusBar()
{
wxString s;
if (!m_sock->IsConnected())
{
s.Printf(_("Not connected"));
}
else
{
wxIPV4address addr;
m_sock->GetPeer(addr);
s.Printf(_("%s : %d"), (addr.Hostname()).c_str(), addr.Service());
}
#if wxUSE_STATUSBAR
SetStatusText(s, 1);
#endif // wxUSE_STATUSBAR
m_menuSocket->Enable(CLIENT_OPEN, !m_sock->IsConnected() && !m_busy);
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());
}