wxSockets hell Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Sickboy
Experienced Solver
Experienced Solver
Posts: 91
Joined: Wed Mar 16, 2005 10:30 pm
Location: Germany

wxSockets hell

Post by Sickboy » Thu Mar 22, 2007 12:09 am

I'm using the Sockets example i just want to sent datas from the server to the connected clients every 500ms. for this i created a timer in the server class which calls following event:

Code: Select all

void MyFrame::OnTimer(wxTimerEvent&event)
{
	if (m_server->IsConnected())
	{
		const wxChar* buf1 = _("Test Message(less than 256 chars!)");
		int len  = (unsigned char)((wxStrlen(buf1) + 1) * sizeof(wxChar));

		//m_server->SetFlags(wxSOCKET_WAITALL);
                        m_server->SetFlags(wxSOCKET_NOWAIT);
		m_server->Write(buf1, len);
		if (m_server->Error())
		{
			if		(m_server->LastError() == wxSOCKET_INVADDR )
					wxLogDebug(wxT("wxSOCKET_INVADDR"));
			else if (m_server->LastError() == wxSOCKET_IOERR  )
					wxLogDebug(wxT("wxSOCKET_IOERR "));
			else if (m_server->LastError() == wxSOCKET_INVOP   )
					wxLogDebug(wxT("wxSOCKET_INVOP  "));
			else if (m_server->LastError() == wxSOCKET_INVSOCK   )
					wxLogDebug(wxT("wxSOCKET_INVSOCK  "));
			else if (m_server->LastError() == wxSOCKET_INVPORT    )
					wxLogDebug(wxT("wxSOCKET_INVPORT   "));
			else if (m_server->LastError() == wxSOCKET_WOULDBLOCK   )
					wxLogDebug(wxT("wxSOCKET_WOULDBLOCK  "));
			else if (m_server->LastError() == wxSOCKET_TIMEDOUT   )
					wxLogDebug(wxT("wxSOCKET_TIMEDOUT  "));
			else if (m_server->LastError() == wxSOCKET_MEMERR    )
					wxLogDebug(wxT("wxSOCKET_MEMERR   "));
			else if (m_server->LastError() == wxSOCKET_MEMERR    )
					wxLogDebug(wxT("wxSOCKET_NOERROR    "));
		}
	}
}
i get the error message wxSOCKET_INVSOCK with the code above.
When i use wxSOCKET_WAITALL it crash at the Write method.

I made no modification in the client or elsewhere in the server (without the timer methods m_timer->SetOwner(this,TIMER_ID); and m_timer->Start(500); )

The same Write function works inside each of the 3 Tests.

Any idea what is wrong ???

My System:
- wxMSW 2.8.0 VC 7 WinXP-

thanks in advance,
Stefan

DonSixto
Earned a small fee
Earned a small fee
Posts: 15
Joined: Thu Sep 14, 2006 5:35 pm

Post by DonSixto » Thu Mar 22, 2007 3:41 am

Where may I see the sockets example ?
Is m_server the accepted socket ?
You can't write on the server socket directly.

upCASE
Site Admin
Site Admin
Posts: 3176
Joined: Mon Aug 30, 2004 6:55 am
Location: Germany, Cologne

Post by upCASE » Thu Mar 22, 2007 8:31 am

Hi!
In addition to what DonSixto said, I conclude that m_server is the wxSocketServer. This is used to listen for incoming connections and accept them. It is *not* the end point used for communication.

In OnServerEvent() the m_server accepts an incoming connection with a new wxSocketBase. This socket is the end point and you can write date to it, which will be received by the client. Feeding data to the server itself doesn't do anything, as it is not a connected end point. It more or less simple lurks around waiting for connections.

To do what you want, modify OnServerEvent() and store the sock pointer in an array or vector. In you timer iterate over the vector and send the data to each sock in the vector.
OS: OpenSuSE, Ubuntu, Win XP Pro
wx: svn
Compiler: gcc 4.5.1, VC 2008, eVC 4

"If it was hard to write it should be hard to read..." - the unknown coder
"Try not! Do. Or do not. There is no try." - Yoda

Sickboy
Experienced Solver
Experienced Solver
Posts: 91
Joined: Wed Mar 16, 2005 10:30 pm
Location: Germany

Post by Sickboy » Thu Mar 22, 2007 11:17 am

Thanks for the quick help. Now my server sends without an error message, but my client OnSocketEvent event handler doesn't respond on the sent packages :?

That's how i establish the connection on the client side.

Code: Select all

void MyFrame::OnOpenConnection(wxCommandEvent& WXUNUSED(event))
{
  wxIPV4address addr;

  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->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);
  m_sock->Notify(true);
  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 !"));
  }

  UpdateStatusBar();
}
And that's the Server event which store the m_SendingSocket

Code: Select all

void MyFrame::OnServerEvent(wxSocketEvent& event)
{
  wxString s = _("OnServerEvent: ");

  switch(event.GetSocketEvent())
  {
    case wxSOCKET_CONNECTION : s.Append(_("wxSOCKET_CONNECTION\n")); break;
    default                  : s.Append(_("Unexpected event !\n")); break;
  }

  m_text->AppendText(s);

  // Currently we just accept one client ! If another one is connecting
  // kick the existing
  if (m_SendingSocket)
  {
	  delete m_SendingSocket;
	  m_SendingSocket = NULL;
  }

  m_SendingSocket = m_server->Accept(false);

  if (m_SendingSocket)
  {
    m_text->AppendText(_("New client connection accepted\n\n"));
	m_timer.SetOwner(this, TIMER_ID);
	m_timer.Start(1000);
  }
  else
  {
    m_text->AppendText(_("Error: couldn't accept a new connection\n\n"));
	m_timer.Stop();
    return;
  }

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

  m_numClients++;
  UpdateStatusBar();
}
What is wrong ?

Thanks

upCASE
Site Admin
Site Admin
Posts: 3176
Joined: Mon Aug 30, 2004 6:55 am
Location: Germany, Cologne

Post by upCASE » Thu Mar 22, 2007 11:30 am

Hi!
So connecting the client to the server and accepting the connection on the server works, right?

Can we see the potion of code where you send from the server and receive in the client?
Besides that, m_numClients++; is pretty useless when there is only one connection ;). And you should use Destroy() instead of simply deleting the socket.
OS: OpenSuSE, Ubuntu, Win XP Pro
wx: svn
Compiler: gcc 4.5.1, VC 2008, eVC 4

"If it was hard to write it should be hard to read..." - the unknown coder
"Try not! Do. Or do not. There is no try." - Yoda

Sickboy
Experienced Solver
Experienced Solver
Posts: 91
Joined: Wed Mar 16, 2005 10:30 pm
Location: Germany

Post by Sickboy » Thu Mar 22, 2007 11:40 am

The sending function you can see in my first posting. It's the timer event handler, but now with m_SendingSocket instead of m_server.

The receive function on the client side is the one from the example:

Code: Select all

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();
}
So i would expect at least an "wxSOCKET_INPUT" output in my client window each 500 ms, but nothing happens.

upCASE
Site Admin
Site Admin
Posts: 3176
Joined: Mon Aug 30, 2004 6:55 am
Location: Germany, Cologne

Post by upCASE » Thu Mar 22, 2007 11:56 am

Hmm..
Maybe a stupid question, but did you use SetEventHandler() on the client socket? I don't see it in your OnOpenConnection()... If no event handler is assigned, not event would be received.
OS: OpenSuSE, Ubuntu, Win XP Pro
wx: svn
Compiler: gcc 4.5.1, VC 2008, eVC 4

"If it was hard to write it should be hard to read..." - the unknown coder
"Try not! Do. Or do not. There is no try." - Yoda

Sickboy
Experienced Solver
Experienced Solver
Posts: 91
Joined: Wed Mar 16, 2005 10:30 pm
Location: Germany

Post by Sickboy » Thu Mar 22, 2007 12:25 pm

The SetEventHandler() is defined in the ctor of my client frame.

Code: Select all

// 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);
I overlooked that i receive the socket event exactly one time.
So in the client output window appears:

Welcome to wxSocket demo: Client
Client ready

Trying to connect (timeout = 10 sec) ...
Succeeded ! Connection established
OnSocketEvent: wxSOCKET_INPUT


but just one time and not every 500ms

upCASE
Site Admin
Site Admin
Posts: 3176
Joined: Mon Aug 30, 2004 6:55 am
Location: Germany, Cologne

Post by upCASE » Thu Mar 22, 2007 12:46 pm

Hi!
The problem seems to be that you never read anything from the socket. I guess it should still emit the event, but it doesn't. However, I used Discard() in the client on input and I was able to receive the next event.
OS: OpenSuSE, Ubuntu, Win XP Pro
wx: svn
Compiler: gcc 4.5.1, VC 2008, eVC 4

"If it was hard to write it should be hard to read..." - the unknown coder
"Try not! Do. Or do not. There is no try." - Yoda

Sickboy
Experienced Solver
Experienced Solver
Posts: 91
Joined: Wed Mar 16, 2005 10:30 pm
Location: Germany

Post by Sickboy » Thu Mar 22, 2007 12:54 pm

Thank you upCASE !
Discarding or reading the socket was the solution.
imho this should be part of the example...
anyway thanks again :)

upCASE
Site Admin
Site Admin
Posts: 3176
Joined: Mon Aug 30, 2004 6:55 am
Location: Germany, Cologne

Post by upCASE » Thu Mar 22, 2007 1:23 pm

Actually this problem does not arise in the sample, as with each of the tests the socket gets read after sending some data.
I still wonder why this happens... I guess, no, I know :) that wxSocket classes could need some more work and bug fixing.
Well, glad it works at last :)
OS: OpenSuSE, Ubuntu, Win XP Pro
wx: svn
Compiler: gcc 4.5.1, VC 2008, eVC 4

"If it was hard to write it should be hard to read..." - the unknown coder
"Try not! Do. Or do not. There is no try." - Yoda

Post Reply