Tuesday, January 23, 2018

UDP/TCP Socket Programming with wxWidgets

  1. Introduction
  2. UDP
  3. TCP
  4. References


In this article, UDP and TCP socket programming using wxWidgets is discussed. For that wxWidgets needs to be installed in your machine. Installing wxWidgets on Windows and Linux platforms can be seen at the following link.
Sockets are used to send and receive data on a network such as the Internet. Almost all modern operating systems support socket layer to transfer data using TCP or UDP. But programming sockets on different platforms usually involves platform specific tweaks. wxWidgets support socket classes which allow you to use sockets for transferring data without concerning about the platform. These classes can be used in various ways and some of them are discussed in the following sections.


UDP (User Datagram Protocol) can be used to send messages (also referred as Datagrams) on IP (Internet Protocol) network. UDP uses a simple connectionless communication model avoiding overheads in the protocol stack. It only uses checksum for data integrity and it does not care assurance of delivery, error correction, and ordering of data in receiving. It is suitable to send data where timeliness has higher priority than error checking and correction such as voice over IP.

After installing wxWidgets, there is a socket example in 'samples' folder [GZ09]. The example is quite complete showing various type of connections. As a result, it is a bit complex. That is why, I would like to present a simpler example - ce_wx_udp.cpp - which includes only UDP part at the follwing link.


At the beginning of the program, required headers and type of IP address are defined as follow.
#include "wx/wx.h"
#include "wx/socket.h"
#if wxUSE_IPV6
    typedef wxIPV6address IPaddress;
    typedef wxIPV4address IPaddress;
Thereafter, IP address and port number to be used are defined in creating a UDP socket. And event handlers are defined for it.
// Create the address - defaults to localhost:0 initially
IPaddress addr;

// Create the socket
sock = new wxDatagramSocket(addr);

// Setup the event handler
sock->SetEventHandler( *this, SOCKET_ID);

RecvFrom method is used to read data in OnSocketEvent.
n = sock->RecvFrom(addr, buf, sizeof(buf)).LastCount();

SendTo method is used to send data after defining remote host and port number.
IPaddress raddr;
sock->SendTo(raddr, buf,n)

To test the program, Hercules Utility which is available for free at https://www.hw-group.com/products /hercules/index_en.html can be used. After building and running the program using the following commands, sending and receiving of data can be seen as illustrated in the following figure.
g++ ce_wx_udp.cpp `wx-config --cxxflags --libs` -o ce_wx_udp
gksudo ./ce_wx_udp

Figure. Using Hercules utility.

Figure. Sending and receiving data using UDP.


TCP (Transmission Control Protocol) provides reliable, ordered, and error-checked delivery of stream of data. Connections must be established to transfer data. TCP server waits for a connection request and TCP client requests a connection to establish.

TCP Server

TCP server passively listens to a port number to accept connection requests from clients. An example TCP server program - ce_wx_tcp_server.cpp - is shown at the following link [GZ09].


In the frame constructor, a socket server is created with the port number to listen and an event handler is defined.
// Create the address - defaults to localhost:0 initially
IPaddress addr;

// Create the socket
sock = new wxSocketServer(addr);

// Setup the event handler and subscribe to connection events
sock->SetEventHandler( *this, SERVER_ID);

Again, in OnServerEvent handler, the requested connection is accepted and event handlers for the connected socket are defined. Thereafter, the number of clients is updated.
wxSocketBase *sockBase;
sockBase = sock->Accept(false);

sockBase->SetEventHandler( *this, SOCKET_ID);

SetStatusText(wxString::Format(wxT("%d  clients connected"),numClients), 1);

Data can be read in many different ways in OnSocketEvent depending on socket settings. It is important to use correct settings. The details can be read in Chapter 18 of 'Cross-Platform GUI Programming with wxWidgets' [SH06] by Julian Smart. In this example, it is assumed that the client sends the length of the message at the first byte of the data, and wxSOCKET_WAITALL is used to wait until all the bytes in the message are received.
// Read the size @ first byte
unsigned char len;
sockBase->Read(&len, 1);

char buf[256];
// Read the message
wxUint32 lenRd = sockBase->Read(buf, len).LastCount();

After receiving the message, the server replies 'OK' to the client with its length '0x02' at the first byte.
len = 2;
buf[0] = 'O';
buf[1] = 'K';
sockBase->Write(buf, len);

When the connection is lost, in wxSOCKET_LOST OnSocketEvent, the socket is destroyed.

When the program is built and run, it will wait for connections from clients as illustrated in the following figure.
g++ ce_wx_tcp_server.cpp `wx-config --cxxflags --libs` -o ce_wx_tcp_server
gksudo ./ce_wx_tcp_server

Figure. TCP server

TCP Client

A TCP client connects to a TCP server and transfers data. An example TCP client pragram - ce_wx_tcp_client.cpp - is shown in the following link [Gar99].


A socket is created in the frame constructor and event handlers are defined.
 // Create the socket
 sock = new wxSocketClient();
 // Setup the event handler and subscribe to most events
 sock->SetEventHandler( *this, SOCKET_ID);

After building and running the program using the following commands, you can connect it to the TCP server which was discussed in previous section. Click File→Open session to connect to the server.
g++ ce_wx_tcp_client.cpp `wx-config --cxxflags --libs` -o ce_wx_tcp_client
gksudo ./ce_wx_tcp_client

Figure. Opening a session from the TCP client.

Connect method is used to connect to the server after defining the hostname and port number.
IPaddress addr;
sock->Connect(addr, false);

Once the connection is established, click 'Send' button to send the message to the server. As shown in the following code, the message buffer preceded with its length byte is sent using 'Write' method.
void MyFrame::OnSend(wxCommandEvent& WXUNUSED(event))
 wxString str = txtSend->GetValue();
 wxCharBuffer buffer = str.ToUTF8();
 size_t txn = str.length();
 unsigned char len;
 len = txn;
 sock->Write(&len, 1);//send the length of the message first
 if (sock->Write(buffer.data(), txn).LastCount() != txn)
  txtRx->AppendText(wxT("Write error.\n"));
 else {
  txtRx->AppendText("Tx: " + str + "\n");

As in the TCP server code, 'Read' method is used to read the data in wxSOCKET_INPUT OnSocketEvent. Click File→Close session to close the connection. The following figures illustrate the sending and receiving of data by the server and the client.
wxUint32 lenRd = sockBase->Read(buf, len).LastCount();

Figure. Sending and receiving of data by TCP client.

Figure. Receiving and sending of data by TCP server.

Related Posts


[Gar99] Guillermo Rodriguez Garcia, Client for wxSocket demo, 1999.
url: https://github.com/wxWidgets/wxWidgets/blob/master/samples/sockets/client.cpp.

[GZ09] Guillermo Rodriguez Garcia and Vadim Zeitlin, Server for wxSocket demo, 2009.
url: https://github.com/wxWidgets/wxWidgets/blob/master/samples/sockets/server.cpp.

[SH06] Julian Smart and Kevin Hock, Cross-Platform GUI Programming with wxWidgets, 2006.
Pearson Education, Inc. ISBN: 0-13-147381-6.

No comments:

Post a Comment

Comments are moderated and don't be surprised if your comment does not appear promptly.