Help with UDP communication

This is a discussion on Help with UDP communication within the C++ Programming forums, part of the General Programming Boards category; So i'm creating an application that creates a connection between a PIC32 microprocessor and n number of clients running on ...

  1. #1
    Registered User
    Join Date
    Aug 2012
    Posts
    3

    Question Help with UDP communication

    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;
    }

  2. #2
    Registered User
    Join Date
    Aug 2012
    Posts
    3
    Nevermind, I got it working.

    Well sort of....

    It only allows me to have one instance of my client software running - which is a problem. There is supposed to be 3 - 5 programs grabbing this data.

  3. #3
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,269
    So what was your question anyway?
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  4. #4
    Registered User
    Join Date
    Oct 2006
    Posts
    2,150
    Quote Originally Posted by WattMood View Post
    It only allows me to have one instance of my client software running - which is a problem. There is supposed to be 3 - 5 programs grabbing this data.
    if you're explicitly binding to a specific port number, then one is all you're allowed to have. I don't know of any operating system out there that will allow two separate processes bind to the same port.

  5. #5
    Registered User
    Join Date
    Aug 2012
    Posts
    3
    Quote Originally Posted by Elkvis View Post
    if you're explicitly binding to a specific port number, then one is all you're allowed to have. I don't know of any operating system out there that will allow two separate processes bind to the same port.
    Ultimately that was my problem. UDP will not allow you to have multiple applications on the same port since the binding is what tells the OS which app to give the data to.

    Trying to synchronize binding and unbinding was absurd so i just switched over to a TCP model for the solution and it works wonderfully

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Communication using MPI
    By Cell in forum Linux Programming
    Replies: 9
    Last Post: 08-13-2009, 02:28 AM
  2. PHP to C++ Communication
    By Dae in forum C++ Programming
    Replies: 3
    Last Post: 07-27-2009, 09:48 AM
  3. communication
    By Tux0r in forum C++ Programming
    Replies: 1
    Last Post: 07-09-2009, 03:53 AM
  4. Looking for communication lib
    By BrownB in forum C Programming
    Replies: 3
    Last Post: 04-27-2005, 10:01 AM
  5. C++ and PHP communication
    By Korhedron in forum Game Programming
    Replies: 4
    Last Post: 01-12-2004, 05:37 AM

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21