So i'm creating an application that creates a connection between a PIC32 microprocessor and n number of clients running on a host computer. To do this I have created a local host program that takes serial data coming from the PIC and broadcasts it on a local UDP network so all the programs can use the data if they would like to.
PIC32 --RS232--> LocalHost ---UDP---> Multiple clients
(Hope this makes sense)
My LocalHost program properly decodes the message and appears to broadcast it to UDP. But my little test client app receives nothing. The test client is just a text box that echoes the UDP data.
The local host is written in C++ since it must work in Win, Linux and Solaris. The test client is written in c# for speed.
So here's the code
Test Client:
Code:
public partial class frmMain : Form
{
Socket _UDPsocket;
private IPAddress _ipAddressClient = IPAddress.Any;
private IPAddress _ipAddressServer = IPAddress.Parse("127.0.0.1");
private short _portNumberClient = 2425;
private short _portNumberServer = 2425;
private IPEndPoint ipepServer, ipepClient;
private EndPoint epClient, epServer;
private byte[] _dataPacket = new byte[1024];
public delegate void AddToLogDelegate(string text);
public delegate void txtLog_ScrollToEndDelegate();
public frmMain()
{
InitializeComponent();
}
private void frmMain_Load(object sender, EventArgs e)
{
InitializeEthernetPort();
}
private void InitializeEthernetPort()
{
AddToLog("Initializing Ethernet Port");
try
{
// Set up a UDP socket
_UDPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
// Assign the local address and listen on the specified port
ipepServer = new IPEndPoint(_ipAddressServer, _portNumberServer);
epServer = (EndPoint)ipepServer;
ipepClient = new IPEndPoint(_ipAddressClient, _portNumberClient);
epClient = (EndPoint)ipepClient;
_UDPsocket.Bind(epClient);
_UDPsocket.BeginReceiveFrom(_dataPacket, 0, _dataPacket.Length, SocketFlags.None, ref epServer,
new AsyncCallback(UDP_DataReceived), null);
AddToLog("Ethernet port started successfully");
}
catch (System.Net.Sockets.SocketException exception)
{
_portNumberClient++;
InitializeEthernetPort();
}
}
private void UDP_DataReceived(IAsyncResult ar)
{
try
{
_UDPsocket.EndReceiveFrom(ar, ref epServer);
string returnData = Encoding.ASCII.GetString(_dataPacket) + Environment.NewLine;
AddToLog("Received: " + returnData + Environment.NewLine);
_UDPsocket.BeginReceiveFrom(_dataPacket, 0, _dataPacket.Length, SocketFlags.None, ref epServer, new AsyncCallback(UDP_DataReceived), null);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "SGSServerUDP", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
And then here is the server code (a little more complicated). I used a open source class called Practical Socket for the UDP connection.
PracticalSocket.h
Code:
/* * C++ sockets on Unix and Windows * Copyright (C) 2002 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __PRACTICALSOCKET_INCLUDED__ #define __PRACTICALSOCKET_INCLUDED__ #include <string> // For string #include <exception> // For exception class using namespace std; /** * Signals a problem with the execution of a socket call. */ class SocketException : public exception { public: /** * Construct a SocketException with a explanatory message. * @param message explanatory message * @param incSysMsg true if system message (from strerror(errno)) * should be postfixed to the user provided message */ SocketException(const string &message, bool inclSysMsg = false) throw(); /** * Provided just to guarantee that no exceptions are thrown. */ ~SocketException() throw(); /** * Get the exception message * @return exception message */ const char *what() const throw(); private: string userMessage; // Exception message }; /** * Base class representing basic communication endpoint */ class Socket { public: /** * Close and deallocate this socket */ ~Socket(); /** * Get the local address * @return local address of socket * @exception SocketException thrown if fetch fails */ string getLocalAddress() throw(SocketException); /** * Get the local port * @return local port of socket * @exception SocketException thrown if fetch fails */ unsigned short getLocalPort() throw(SocketException); /** * Set the local port to the specified port and the local address * to any interface * @param localPort local port * @exception SocketException thrown if setting local port fails */ void setLocalPort(unsigned short localPort) throw(SocketException); /** * Set the local port to the specified port and the local address * to the specified address. If you omit the port, a random port * will be selected. * @param localAddress local address * @param localPort local port * @exception SocketException thrown if setting local port or address fails */ void setLocalAddressAndPort(const string &localAddress, unsigned short localPort = 0) throw(SocketException); /** * If WinSock, unload the WinSock DLLs; otherwise do nothing. We ignore * this in our sample client code but include it in the library for * completeness. If you are running on Windows and you are concerned * about DLL resource consumption, call this after you are done with all * Socket instances. If you execute this on Windows while some instance of * Socket exists, you are toast. For portability of client code, this is * an empty function on non-Windows platforms so you can always include it. * @param buffer buffer to receive the data * @param bufferLen maximum number of bytes to read into buffer * @return number of bytes read, 0 for EOF, and -1 for error * @exception SocketException thrown WinSock clean up fails */ static void cleanUp() throw(SocketException); /** * Resolve the specified service for the specified protocol to the * corresponding port number in host byte order * @param service service to resolve (e.g., "http") * @param protocol protocol of service to resolve. Default is "tcp". */ static unsigned short resolveService(const string &service, const string &protocol = "tcp"); private: // Prevent the user from trying to use value semantics on this object Socket(const Socket &sock); void operator=(const Socket &sock); protected: int sockDesc; // Socket descriptor Socket(int type, int protocol) throw(SocketException); Socket(int sockDesc); }; /** * Socket which is able to connect, send, and receive */ class CommunicatingSocket : public Socket { public: /** * Establish a socket connection with the given foreign * address and port * @param foreignAddress foreign address (IP address or name) * @param foreignPort foreign port * @exception SocketException thrown if unable to establish connection */ void connect(const string &foreignAddress, unsigned short foreignPort) throw(SocketException); /** * Write the given buffer to this socket. Call connect() before * calling send() * @param buffer buffer to be written * @param bufferLen number of bytes from buffer to be written * @exception SocketException thrown if unable to send data */ void send(const void *buffer, int bufferLen) throw(SocketException); /** * Read into the given buffer up to bufferLen bytes data from this * socket. Call connect() before calling recv() * @param buffer buffer to receive the data * @param bufferLen maximum number of bytes to read into buffer * @return number of bytes read, 0 for EOF, and -1 for error * @exception SocketException thrown if unable to receive data */ int recv(void *buffer, int bufferLen) throw(SocketException); /** * Get the foreign address. Call connect() before calling recv() * @return foreign address * @exception SocketException thrown if unable to fetch foreign address */ string getForeignAddress() throw(SocketException); /** * Get the foreign port. Call connect() before calling recv() * @return foreign port * @exception SocketException thrown if unable to fetch foreign port */ unsigned short getForeignPort() throw(SocketException); protected: CommunicatingSocket(int type, int protocol) throw(SocketException); CommunicatingSocket(int newConnSD); }; /** * TCP socket for communication with other TCP sockets */ class TCPSocket : public CommunicatingSocket { public: /** * Construct a TCP socket with no connection * @exception SocketException thrown if unable to create TCP socket */ TCPSocket() throw(SocketException); /** * Construct a TCP socket with a connection to the given foreign address * and port * @param foreignAddress foreign address (IP address or name) * @param foreignPort foreign port * @exception SocketException thrown if unable to create TCP socket */ TCPSocket(const string &foreignAddress, unsigned short foreignPort) throw(SocketException); private: // Access for TCPServerSocket::accept() connection creation friend class TCPServerSocket; TCPSocket(int newConnSD); }; /** * TCP socket class for servers */ class TCPServerSocket : public Socket { public: /** * Construct a TCP socket for use with a server, accepting connections * on the specified port on any interface * @param localPort local port of server socket, a value of zero will * give a system-assigned unused port * @param queueLen maximum queue length for outstanding * connection requests (default 5) * @exception SocketException thrown if unable to create TCP server socket */ TCPServerSocket(unsigned short localPort, int queueLen = 5) throw(SocketException); /** * Construct a TCP socket for use with a server, accepting connections * on the specified port on the interface specified by the given address * @param localAddress local interface (address) of server socket * @param localPort local port of server socket * @param queueLen maximum queue length for outstanding * connection requests (default 5) * @exception SocketException thrown if unable to create TCP server socket */ TCPServerSocket(const string &localAddress, unsigned short localPort, int queueLen = 5) throw(SocketException); /** * Blocks until a new connection is established on this socket or error * @return new connection socket * @exception SocketException thrown if attempt to accept a new connection fails */ TCPSocket *accept() throw(SocketException); private: void setListen(int queueLen) throw(SocketException); }; /** * UDP socket class */ class UDPSocket : public CommunicatingSocket { public: /** * Construct a UDP socket * @exception SocketException thrown if unable to create UDP socket */ UDPSocket() throw(SocketException); /** * Construct a UDP socket with the given local port * @param localPort local port * @exception SocketException thrown if unable to create UDP socket */ UDPSocket(unsigned short localPort) throw(SocketException); /** * Construct a UDP socket with the given local port and address * @param localAddress local address * @param localPort local port * @exception SocketException thrown if unable to create UDP socket */ UDPSocket(const string &localAddress, unsigned short localPort) throw(SocketException); /** * Unset foreign address and port * @return true if disassociation is successful * @exception SocketException thrown if unable to disconnect UDP socket */ void disconnect() throw(SocketException); /** * Send the given buffer as a UDP datagram to the * specified address/port * @param buffer buffer to be written * @param bufferLen number of bytes to write * @param foreignAddress address (IP address or name) to send to * @param foreignPort port number to send to * @return true if send is successful * @exception SocketException thrown if unable to send datagram */ void sendTo(const void *buffer, int bufferLen, const string &foreignAddress, unsigned short foreignPort) throw(SocketException); /** * Read read up to bufferLen bytes data from this socket. The given buffer * is where the data will be placed * @param buffer buffer to receive data * @param bufferLen maximum number of bytes to receive * @param sourceAddress address of datagram source * @param sourcePort port of data source * @return number of bytes received and -1 for error * @exception SocketException thrown if unable to receive datagram */ int recvFrom(void *buffer, int bufferLen, string &sourceAddress, unsigned short &sourcePort) throw(SocketException); /** * Set the multicast TTL * @param multicastTTL multicast TTL * @exception SocketException thrown if unable to set TTL */ void setMulticastTTL(unsigned char multicastTTL) throw(SocketException); /** * Join the specified multicast group * @param multicastGroup multicast group address to join * @exception SocketException thrown if unable to join group */ void joinGroup(const string &multicastGroup) throw(SocketException); /** * Leave the specified multicast group * @param multicastGroup multicast group address to leave * @exception SocketException thrown if unable to leave group */ void leaveGroup(const string &multicastGroup) throw(SocketException); private: void setBroadcast(); }; #endif
PracticalSocket.cpp
Code:
/* * C++ sockets on Unix and Windows * Copyright (C) 2002 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "PracticalSocket.h" #ifdef WIN32 #include <winsock.h> // For socket(), connect(), send(), and recv() typedef int socklen_t; typedef char raw_type; // Type used for raw data on this platform #else #include <sys/types.h> // For data types #include <sys/socket.h> // For socket(), connect(), send(), and recv() #include <netdb.h> // For gethostbyname() #include <arpa/inet.h> // For inet_addr() #include <unistd.h> // For close() #include <netinet/in.h> // For sockaddr_in typedef void raw_type; // Type used for raw data on this platform #endif #include <errno.h> // For errno using namespace std; #ifdef WIN32 static bool initialized = false; #endif // SocketException Code SocketException::SocketException(const string &message, bool inclSysMsg) throw() : userMessage(message) { if (inclSysMsg) { userMessage.append(": "); userMessage.append(strerror(errno)); } } SocketException::~SocketException() throw() { } const char *SocketException::what() const throw() { return userMessage.c_str(); } // Function to fill in address structure given an address and port static void fillAddr(const string &address, unsigned short port, sockaddr_in &addr) { memset(&addr, 0, sizeof(addr)); // Zero out address structure addr.sin_family = AF_INET; // Internet address hostent *host; // Resolve name if ((host = gethostbyname(address.c_str())) == NULL) { // strerror() will not work for gethostbyname() and hstrerror() // is supposedly obsolete throw SocketException("Failed to resolve name (gethostbyname())"); } addr.sin_addr.s_addr = *((unsigned long *) host->h_addr_list[0]); addr.sin_port = htons(port); // Assign port in network byte order } // Socket Code Socket::Socket(int type, int protocol) throw(SocketException) { #ifdef WIN32 if (!initialized) { WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(2, 0); // Request WinSock v2.0 if (WSAStartup(wVersionRequested, &wsaData) != 0) { // Load WinSock DLL throw SocketException("Unable to load WinSock DLL"); } initialized = true; } #endif // Make a new socket if ((sockDesc = socket(PF_INET, type, protocol)) < 0) { throw SocketException("Socket creation failed (socket())", true); } } Socket::Socket(int sockDesc) { this->sockDesc = sockDesc; } Socket::~Socket() { #ifdef WIN32 ::closesocket(sockDesc); #else ::close(sockDesc); #endif sockDesc = -1; } string Socket::getLocalAddress() throw(SocketException) { sockaddr_in addr; unsigned int addr_len = sizeof(addr); if (getsockname(sockDesc, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) { throw SocketException("Fetch of local address failed (getsockname())", true); } return inet_ntoa(addr.sin_addr); } unsigned short Socket::getLocalPort() throw(SocketException) { sockaddr_in addr; unsigned int addr_len = sizeof(addr); if (getsockname(sockDesc, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) { throw SocketException("Fetch of local port failed (getsockname())", true); } return ntohs(addr.sin_port); } void Socket::setLocalPort(unsigned short localPort) throw(SocketException) { // Bind the socket to its port sockaddr_in localAddr; memset(&localAddr, 0, sizeof(localAddr)); localAddr.sin_family = AF_INET; localAddr.sin_addr.s_addr = htonl(INADDR_ANY); localAddr.sin_port = htons(localPort); if (bind(sockDesc, (sockaddr *) &localAddr, sizeof(sockaddr_in)) < 0) { throw SocketException("Set of local port failed (bind())", true); } } void Socket::setLocalAddressAndPort(const string &localAddress, unsigned short localPort) throw(SocketException) { // Get the address of the requested host sockaddr_in localAddr; fillAddr(localAddress, localPort, localAddr); if (bind(sockDesc, (sockaddr *) &localAddr, sizeof(sockaddr_in)) < 0) { throw SocketException("Set of local address and port failed (bind())", true); } } void Socket::cleanUp() throw(SocketException) { #ifdef WIN32 if (WSACleanup() != 0) { throw SocketException("WSACleanup() failed"); } #endif } unsigned short Socket::resolveService(const string &service, const string &protocol) { struct servent *serv; /* Structure containing service information */ if ((serv = getservbyname(service.c_str(), protocol.c_str())) == NULL) return atoi(service.c_str()); /* Service is port number */ else return ntohs(serv->s_port); /* Found port (network byte order) by name */ } // CommunicatingSocket Code CommunicatingSocket::CommunicatingSocket(int type, int protocol) throw(SocketException) : Socket(type, protocol) { } CommunicatingSocket::CommunicatingSocket(int newConnSD) : Socket(newConnSD) { } void CommunicatingSocket::connect(const string &foreignAddress, unsigned short foreignPort) throw(SocketException) { // Get the address of the requested host sockaddr_in destAddr; fillAddr(foreignAddress, foreignPort, destAddr); // Try to connect to the given port if (::connect(sockDesc, (sockaddr *) &destAddr, sizeof(destAddr)) < 0) { throw SocketException("Connect failed (connect())", true); } } void CommunicatingSocket::send(const void *buffer, int bufferLen) throw(SocketException) { if (::send(sockDesc, (raw_type *) buffer, bufferLen, 0) < 0) { throw SocketException("Send failed (send())", true); } } int CommunicatingSocket::recv(void *buffer, int bufferLen) throw(SocketException) { int rtn; if ((rtn = ::recv(sockDesc, (raw_type *) buffer, bufferLen, 0)) < 0) { throw SocketException("Received failed (recv())", true); } return rtn; } string CommunicatingSocket::getForeignAddress() throw(SocketException) { sockaddr_in addr; unsigned int addr_len = sizeof(addr); if (getpeername(sockDesc, (sockaddr *) &addr,(socklen_t *) &addr_len) < 0) { throw SocketException("Fetch of foreign address failed (getpeername())", true); } return inet_ntoa(addr.sin_addr); } unsigned short CommunicatingSocket::getForeignPort() throw(SocketException) { sockaddr_in addr; unsigned int addr_len = sizeof(addr); if (getpeername(sockDesc, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) { throw SocketException("Fetch of foreign port failed (getpeername())", true); } return ntohs(addr.sin_port); } // TCPSocket Code TCPSocket::TCPSocket() throw(SocketException) : CommunicatingSocket(SOCK_STREAM, IPPROTO_TCP) { } TCPSocket::TCPSocket(const string &foreignAddress, unsigned short foreignPort) throw(SocketException) : CommunicatingSocket(SOCK_STREAM, IPPROTO_TCP) { connect(foreignAddress, foreignPort); } TCPSocket::TCPSocket(int newConnSD) : CommunicatingSocket(newConnSD) { } // TCPServerSocket Code TCPServerSocket::TCPServerSocket(unsigned short localPort, int queueLen) throw(SocketException) : Socket(SOCK_STREAM, IPPROTO_TCP) { setLocalPort(localPort); setListen(queueLen); } TCPServerSocket::TCPServerSocket(const string &localAddress, unsigned short localPort, int queueLen) throw(SocketException) : Socket(SOCK_STREAM, IPPROTO_TCP) { setLocalAddressAndPort(localAddress, localPort); setListen(queueLen); } TCPSocket *TCPServerSocket::accept() throw(SocketException) { int newConnSD; if ((newConnSD = ::accept(sockDesc, NULL, 0)) < 0) { throw SocketException("Accept failed (accept())", true); } return new TCPSocket(newConnSD); } void TCPServerSocket::setListen(int queueLen) throw(SocketException) { if (listen(sockDesc, queueLen) < 0) { throw SocketException("Set listening socket failed (listen())", true); } } // UDPSocket Code UDPSocket::UDPSocket() throw(SocketException) : CommunicatingSocket(SOCK_DGRAM, IPPROTO_UDP) { setBroadcast(); } UDPSocket::UDPSocket(unsigned short localPort) throw(SocketException) : CommunicatingSocket(SOCK_DGRAM, IPPROTO_UDP) { setLocalPort(localPort); setBroadcast(); } UDPSocket::UDPSocket(const string &localAddress, unsigned short localPort) throw(SocketException) : CommunicatingSocket(SOCK_DGRAM, IPPROTO_UDP) { setLocalAddressAndPort(localAddress, localPort); setBroadcast(); } void UDPSocket::setBroadcast() { // If this fails, we'll hear about it when we try to send. This will allow // system that cannot broadcast to continue if they don't plan to broadcast int broadcastPermission = 1; setsockopt(sockDesc, SOL_SOCKET, SO_BROADCAST, (raw_type *) &broadcastPermission, sizeof(broadcastPermission)); } void UDPSocket::disconnect() throw(SocketException) { sockaddr_in nullAddr; memset(&nullAddr, 0, sizeof(nullAddr)); nullAddr.sin_family = AF_UNSPEC; // Try to disconnect if (::connect(sockDesc, (sockaddr *) &nullAddr, sizeof(nullAddr)) < 0) { #ifdef WIN32 if (errno != WSAEAFNOSUPPORT) { #else if (errno != EAFNOSUPPORT) { #endif throw SocketException("Disconnect failed (connect())", true); } } } void UDPSocket::sendTo(const void *buffer, int bufferLen, const string &foreignAddress, unsigned short foreignPort) throw(SocketException) { sockaddr_in destAddr; fillAddr(foreignAddress, foreignPort, destAddr); // Write out the whole buffer as a single message. if (sendto(sockDesc, (raw_type *) buffer, bufferLen, 0, (sockaddr *) &destAddr, sizeof(destAddr)) != bufferLen) { throw SocketException("Send failed (sendto())", true); } } int UDPSocket::recvFrom(void *buffer, int bufferLen, string &sourceAddress, unsigned short &sourcePort) throw(SocketException) { sockaddr_in clntAddr; socklen_t addrLen = sizeof(clntAddr); int rtn; if ((rtn = recvfrom(sockDesc, (raw_type *) buffer, bufferLen, 0, (sockaddr *) &clntAddr, (socklen_t *) &addrLen)) < 0) { throw SocketException("Receive failed (recvfrom())", true); } sourceAddress = inet_ntoa(clntAddr.sin_addr); sourcePort = ntohs(clntAddr.sin_port); return rtn; } void UDPSocket::setMulticastTTL(unsigned char multicastTTL) throw(SocketException) { if (setsockopt(sockDesc, IPPROTO_IP, IP_MULTICAST_TTL, (raw_type *) &multicastTTL, sizeof(multicastTTL)) < 0) { throw SocketException("Multicast TTL set failed (setsockopt())", true); } } void UDPSocket::joinGroup(const string &multicastGroup) throw(SocketException) { struct ip_mreq multicastRequest; multicastRequest.imr_multiaddr.s_addr = inet_addr(multicastGroup.c_str()); multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(sockDesc, IPPROTO_IP, IP_ADD_MEMBERSHIP, (raw_type *) &multicastRequest, sizeof(multicastRequest)) < 0) { throw SocketException("Multicast group join failed (setsockopt())", true); } } void UDPSocket::leaveGroup(const string &multicastGroup) throw(SocketException) { struct ip_mreq multicastRequest; multicastRequest.imr_multiaddr.s_addr = inet_addr(multicastGroup.c_str()); multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(sockDesc, IPPROTO_IP, IP_DROP_MEMBERSHIP, (raw_type *) &multicastRequest, sizeof(multicastRequest)) < 0) { throw SocketException("Multicast group leave failed (setsockopt())", true); } }
NetworkBridge.h
Code:
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// The Network Bridge is a class that handles transferring data between different protocols. //
// //
// - It opens a serial COM port connection with the I/O controller that is on the CAN network. //
// - All data received through the serial port is echoed/broadcasted to the UDP network. //
// - It allows clients on the UDP network to form a TCP connection to send a request to the CAN network //
// //
// Created by Matthew Wood 8/13/2012 //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
#ifndef NETWORKBRIDGE_H
#define NETWORKBRIDGE_H
#include <iostream>
#include "PracticalSocket.h"
#include "SerialPort.h"
#include "UdpPort.h"
#ifdef WINDOWS
#include <pthread32.h>
#else //LINUX
#include <pthread.h>
#endif
class NetworkBridge
{
public:
NetworkBridge(void); // Default constructor
void CreateBridge(); // Creates the network bridge
void CloseBridge(); // Closes the network bridge
private:
void BroadcastOnUdp( void* ptr, int length ); // Broadcasts a message on the UDP network
void InitializeEthernet(); // Initialize the UDP and TCP networks
void InitializeSerial(); // Initialize the serial port
void ListenForClient(); // Creates a listening thread for making TCP connections
static void* ListenForClientProxy(void* ptr); // Proxy function to allow threading with a class member function
void ListenOnSerial(); // Creates a listening thread for listening to the Serial Port
static void* ListenOnSerialProxy(void* ptr); // Proxy function to allow threading with a class member function
SerialPort serialPort;
UDPSocket udpSocket;
int serialPortNumber, udpPortNumber;
char* ipAddress;
pthread_t TCPConnectionThread,
SerialListenerThread;
};
#endif
NetworkBridge.cpp
Code:
#include "NetworkBridge.h"
/*////////////////////////////////////////////////////////////////
NetworkBridge() //
//
Return: None //
Params: None //
//
The default constructor for the Network Bridge. Sets initial //
values. //
////////////////////////////////////////////////////////////////*/
NetworkBridge::NetworkBridge(void)
{
serialPortNumber = 2;
udpPortNumber = 2424;
ipAddress = "127.0.0.1";
}
/*////////////////////////////////////////////////////////////////
CreateBridge() //
//
Return: void //
Params: None //
//
This function initiates the ports needed to communicate. A //
serial port is set first since it is necessary for all the //
programs functionality. If no serial connection is present //
the program will quit. Second the ethernet ports are opened //
to allow for connections from clients. A UDP port is also //
opened to broadcast all messages coming in on the serial port //
////////////////////////////////////////////////////////////////*/
void NetworkBridge::CreateBridge()
{
InitializeSerial(); // Initialize the Serial port
InitializeEthernet(); // Initialize the UDP and TCP ports
}
void NetworkBridge::CloseBridge()
{
}
void NetworkBridge::BroadcastOnUdp( void* ptr, int length)
{
printf("Broadcasted to UDP: %s\n", (char*)ptr);
udpSocket.sendTo(ptr, length, "127.0.0.1", udpPortNumber);
}
/*////////////////////////////////////////////////////////////////
InitializeSerial() //
//
Return: None //
Params: None //
//
This function initiates the serial port and exits if no //
connection is established. //
////////////////////////////////////////////////////////////////*/
void NetworkBridge::InitializeSerial()
{
printf("Initializing Serial Connection on COM%i... \n", (serialPortNumber+1));
if(serialPort.OpenComPort(serialPortNumber, 9600)) // Open the port at the given baud rate
{
printf("\n\n>> ARTinc Local Host cannot continue without an established serial connection\n>> Please check that the cable is connected and the port is not already in use\n");
exit(1); // Return 1 if unable to open the port
}
pthread_create( &SerialListenerThread, NULL, ListenOnSerialProxy, (void *)this );
}
void NetworkBridge::InitializeEthernet()
{
printf("Initializing UDP port...\n");
udpSocket.setLocalPort(udpPortNumber);
pthread_create( &TCPConnectionThread, NULL, ListenForClientProxy, (void *)this );
}
void NetworkBridge::ListenForClient()
{
printf("Listening for client\n");
}
void* NetworkBridge::ListenForClientProxy(void* ptr)
{
NetworkBridge* nptr = (NetworkBridge*)ptr;
nptr->ListenForClient();
return NULL;
}
/***********************************************************
* ListenOnSerial()
*
* Param: None
* Return: None
*
* ListenOnSerial is a function designed to be run on a thread. It
* listens on the serial port for data and echos it out to the UDP
* network.
*/
void NetworkBridge::ListenOnSerial()
{
int n, length = 0;
unsigned char buf[1];
char tmp;
unsigned char finalBuf[256];
while(true)
{
if(serialPort.PollComport(serialPortNumber, buf, 1) > 0)
{
tmp = buf[0];
if(tmp == 0x02)
{
length = 0;
while(serialPort.PollComport(serialPortNumber, buf, 1)<1);
while(tmp != 0x04)
{
finalBuf[length] = *buf;
length++;
while(serialPort.PollComport(serialPortNumber, buf, 1)<1);
tmp = buf[0];
}
BroadcastOnUdp(finalBuf, length);
}
}
}
}
/***********************************************************
* ListenOnSerialProxy()
*
* Param: None
* Return: None
*
* ListenOnSerialProxy is a proxy function that allows the pthread library to
* use a class member function as a thread. When using pthread you must pass
* a pointer of itself. As a static function it can be used as a thread. It then
* uses the pointer to call the function that would normally be inaccesible.
*
* http://stackoverflow.com/questions/1151582/pthread-function-from-a-class
*
*/
void* NetworkBridge::ListenOnSerialProxy(void* ptr)
{
NetworkBridge* nptr = (NetworkBridge*)ptr;
nptr->ListenOnSerial();
return NULL;
}