tcp.cpp
Go to the documentation of this file.
00001 //
00002 // Tcp.cpp
00003 //
00004 // TCP-Client.
00005 //
00006 
00007 #include "tcp.hpp"
00008 #include "../tools/errorhandler.hpp"
00009 #include "../tools/toolbox.hpp"
00010 #include <stdio.h>      // for sprintf()
00011 
00012 #include <sys/socket.h> // for socket(), bind(), and connect()
00013 #include <arpa/inet.h>  // for sockaddr_in and inet_ntoa()
00014 #include <string.h>     // for memset()
00015 #include <netdb.h>      // for hostent
00016 
00017 
00018 Tcp::Tcp()
00019 {
00020         m_beVerbose = false;
00021         m_connectionSocket = -1;
00022         
00023         m_readThread.m_threadShouldRun = false;
00024         
00025         m_longStringWarningPrinted = false;
00026         m_disconnectFunction = NULL;
00027         m_disconnectFunctionObjPtr = NULL;
00028         m_readFunction = NULL;
00029         m_readFunctionObjPtr = NULL;
00030 
00031 }
00032 
00033 //
00034 // Destruktor.
00035 //
00036 Tcp::~Tcp(void)
00037 {
00038         close();
00039 }
00040 
00041 
00042 //
00043 // Schreibe eine Anzahl Bytes auf die Schnittstelle.
00044 //
00045 // Dieser Aufruf wartet, bis alle Bytes geschrieben wurden.
00046 //
00047 bool Tcp::write(UINT8* buffer, UINT32 numberOfBytes)
00048 {
00049         INT32 bytesSent;
00050         bool result;
00051         INT32* socketPtr = &m_connectionSocket;
00052         
00053         // Sende Daten an das Socket
00054         bytesSent = ::send(*socketPtr, buffer, numberOfBytes, 0);
00055         
00056         if (bytesSent != (INT32)numberOfBytes)
00057         {
00058                 printWarning("Tcp::write: Failed to send data to socket.");
00059                 result = false;
00060         }
00061         else
00062         {
00063                 // Erfolg
00064                 printInfoMessage("Tcp::write: Sent " + toString(numberOfBytes) + " bytes to client.", m_beVerbose);
00065                 result = true;
00066         }
00067 
00068         return result;
00069 }
00070 
00071 
00072 //
00073 // Setzt die Funktion, die bei einem Disconnect-Ereignis aufgerufen wird.
00074 //
00075 void Tcp::setDisconnectCallbackFunction(DisconnectFunction discFunction, void* obj)
00076 {
00077         m_disconnectFunction = discFunction;
00078         m_disconnectFunctionObjPtr = obj;
00079 }
00080 
00081 
00082 
00088 bool Tcp::isOpen()
00089 {
00090         if (m_connectionSocket >= 0)
00091         {
00092 //              printInfoMessage("Tcp::isOpen: Reporting open connection.", m_beVerbose);
00093                 return true;
00094         }
00095 
00096 //      printInfoMessage("Tcp::isOpen: Reporting no connection.", m_beVerbose);
00097         return false;
00098 }
00099 
00100 //
00101 // Definiere die Lese-Callback-Funktion.
00102 //
00103 void Tcp::setReadCallbackFunction(Tcp::ReadFunction readFunction, void* obj)
00104 {
00105         m_readFunction = readFunction;
00106         m_readFunctionObjPtr = obj;
00107 }
00108 
00109 //
00110 // Alternative open-Funktion.
00111 //
00112 bool Tcp::open(UINT32 ipAddress, UINT16 port,  bool enableVerboseDebugOutput)
00113 {
00114         std::string ipAdrStr;
00115         
00116         ipAdrStr = ipAdrToString(ipAddress);
00117                                 
00118         bool result = open(ipAdrStr, port, enableVerboseDebugOutput);
00119         
00120         return result;
00121 }
00122 
00123 
00124 //
00125 // Oeffnet die Verbindung.
00126 //
00127 // -- Wir sind der Client, und wollen uns z.B. mit einem Scanner verbinden --
00128 //
00129 bool Tcp::open(std::string ipAddress, UINT16 port, bool enableVerboseDebugOutput)
00130 {
00131         INT32 result;
00132         m_beVerbose = enableVerboseDebugOutput;
00133 
00134 //      printInfoMessage("Tcp::open: Setting up input buffer with size=" + convertValueToString(requiredInputBufferSize) + " bytes.", m_beVerbose);
00135 //      m_inBuffer.init(requiredInputBufferSize, m_beVerbose);
00136         
00137         printInfoMessage("Tcp::open: Opening connection.", m_beVerbose);
00138         
00139         // Socket erzeugen
00140         m_connectionSocket = -1;        // Keine Verbindung
00141         {
00142                 ScopedLock lock(&m_socketMutex);                // Mutex setzen
00143                 m_connectionSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
00144         }
00145         if (m_connectionSocket  < 0)
00146         {
00147         printError("Tcp::open: socket() failed, aborting.");
00148                 return false;
00149         }
00150 
00151         // Socket ist da. Nun die Verbindung oeffnen.
00152         printInfoMessage("Tcp::open: Connecting. Target address is " + ipAddress + ":" + toString(port) + ".", m_beVerbose);
00153         
00154         struct sockaddr_in addr;
00155         struct hostent *server;
00156         server = gethostbyname(ipAddress.c_str());
00157         memset(&addr, 0, sizeof(addr));                 // Zero out structure
00158         addr.sin_family = AF_INET;
00159         bcopy((char *)server->h_addr, (char *)&addr.sin_addr.s_addr, server->h_length);
00160         addr.sin_port = htons(port);                            // Host-2-Network byte order
00161         result = connect(m_connectionSocket, (sockaddr*)(&addr), sizeof(addr));
00162         if (result < 0)
00163         {
00164                 // Verbindungsversuch ist fehlgeschlagen
00165                 std::string text = "Tcp::open: Failed to open TCP connection to " + ipAddress + ", aborting.";
00166                 printError(text);
00167                 return false;
00168         }
00169 
00170         printInfoMessage("Tcp::open: Connection established. Now starting read thread.", m_beVerbose);
00171 
00172         // Empfangsthread starten
00173         m_readThread.run(this);
00174         
00175         printInfoMessage("Tcp::open: Done, leaving now.", m_beVerbose);
00176 
00177         return true;
00178 }
00179 
00180 
00181 //
00182 // Lese-Thread (Hauptfunktion).
00183 //
00184 void Tcp::readThreadFunction(bool& endThread, UINT16& waitTimeMs)
00185 {
00186         INT32 result;
00187 
00188         // Lesen
00189         result = readInputData();
00190 
00191         // Ergebnis?
00192         if (result < 0)
00193         {
00194                 // Verbindung wurde abgebrochen
00195                 if (m_readThread.m_threadShouldRun == true)
00196                 {
00197                         // Wir sollten eigentlich noch laufen!
00198                         printInfoMessage("Tcp::readThreadMain: Connection is lost! Read thread terminates now.", m_beVerbose);
00199                 }
00200                 waitTimeMs = 0;
00201         }
00202         else if (result == 0)
00203         {
00204                 // Wir haben nichts empfangen. Schlafen und dann weiter...
00205                 waitTimeMs = 1;
00206         }
00207         else
00208         {
00209                 // Wir haben etwas empfangen, also nicht schlafen
00210                 waitTimeMs = 0;
00211         }
00212 }
00213 
00214 //
00215 // Read some data from the TCP connection.
00216 //
00217 INT32 Tcp::readInputData()
00218 {
00219         // Prepare the input buffer
00220         const UINT16 max_length = 8192;
00221         UINT8 inBuffer[max_length];
00222         INT32 recvMsgSize = 0;
00223         
00224         // Ist die Verbindung offen?
00225         if (isOpen() == false)
00226         {
00227                 printError("Tcp::readInputData: Connection is not open, aborting!");
00228                 return -1;
00229         }
00230                 
00231         // Read some data, if any
00232         recvMsgSize = recv(m_connectionSocket, inBuffer, max_length, 0);
00233         if (recvMsgSize < 0)
00234         {
00235                 // Fehler
00236                 printError("Tcp::readInputData: Failed to read data from socket, aborting!");
00237         }
00238         else if (recvMsgSize > 0)
00239         {
00240                 // Erfolg
00241                 printInfoMessage("Tcp::readInputData: Read " + toString(recvMsgSize) + " bytes from the connection.", m_beVerbose);
00242                 
00243                 // Falls eine Callback-Funktion definiert ist, rufe sie auf mit den
00244                 // empfangenen Daten.
00245                 if (m_readFunction != NULL)
00246                 {
00247                         // Die Daten an die Callback-Funktion uebergeben
00248                         UINT32 length_uint32 = (UINT32)recvMsgSize;
00249                         m_readFunction(m_readFunctionObjPtr, inBuffer, length_uint32);
00250                 }
00251                 else
00252                 {
00253                         // Es ist keine Callback-Funktion definiert, also die Daten im
00254                         // lokalen Puffer speichern.
00255                         for (INT32 i = 0; i < recvMsgSize; i++)
00256                         {
00257                                 m_rxBuffer.push_back(inBuffer[i]);
00258                         }
00259                 }
00260         }
00261         else if (recvMsgSize == 0)
00262         {
00263                 // Verbindungsabbruch
00264                 printInfoMessage("Tcp::readInputData: Read 0 bytes - connection is lost!", true);
00265                 
00266                 // Informieren?
00267                 if (m_disconnectFunction != NULL)
00268                 {
00269                         m_disconnectFunction(m_disconnectFunctionObjPtr);
00270                 }
00271                 
00272                 // Mutex setzen
00273                 ScopedLock lock(&m_socketMutex);
00274 
00275                 m_connectionSocket = -1;        // Keine Verbindung mehr
00276         }
00277         
00278         return recvMsgSize;
00279 }
00280 
00281 
00282 //
00283 // Close an open connection, if any.
00284 //
00285 void Tcp::close()
00286 {
00287         printInfoMessage("Tcp::close: Closing Tcp connection.", m_beVerbose);
00288 
00289         if (isOpen() == true)
00290         {
00291                 // Dem Lese-Thread ein Ende signalisieren
00292                 m_readThread.m_threadShouldRun = false;
00293 
00294                 // Verbindung schliessen
00295                 ::close(m_connectionSocket);
00296 
00297                 // Auf das Ende des Empfangsthreads warten
00298                 printInfoMessage("Tcp::close: Waiting for the server thread to terminate...", m_beVerbose);
00299 
00300                 // Thread stoppen
00301                 stopReadThread();
00302         }
00303         else
00304         {
00305                 printInfoMessage("Tcp::close: Nothing to do - no open connection? Aborting.", m_beVerbose);
00306         }
00307 
00308         printInfoMessage("Tcp::close: Done - Connection is now closed.", m_beVerbose);
00309 }
00310 
00311 
00315 void Tcp::stopReadThread()
00316 {
00317         printInfoMessage("Tcp::stopReadThread: Stopping thread.", m_beVerbose);
00318         
00319 //      m_readThread.m_threadShouldRun = false;
00320         m_readThread.join();
00321 
00322         printInfoMessage("Tcp::stopReadThread: Done - Read thread is now closed.", m_beVerbose);
00323 }
00324 
00325 
00326 
00332 UINT32 Tcp::getNumReadableBytes()
00333 {
00334         return m_rxBuffer.size();
00335 }
00336 
00337 
00338 //
00339 // Read function.
00340 //
00341 // 0..bufferLen bytes are returned.
00342 // Return value is the number of returned bytes.
00343 //
00344 // DEPRECATED. Use the callback mechanism instead!
00345 //
00346 UINT32 Tcp::read(UINT8* buffer, UINT32 bufferLen)
00347 {
00348         UINT32 bytesRead = 0;
00349         
00350         // Lesen
00351         while ((getNumReadableBytes() > 0) && (bufferLen > bytesRead))
00352         {
00353                 buffer[bytesRead] = m_rxBuffer.front();
00354                 m_rxBuffer.pop_front();
00355                 bytesRead += 1; // m_inBuffer.read(buffer, bufferLen);
00356         }
00357         
00358         return bytesRead;
00359 }
00360 
00361 
00367 std::string Tcp::readString(UINT8 delimiter)
00368 {
00369         UINT8 c = delimiter;
00370         std::string outString;
00371         const UINT16 maxStringLength = 8192;
00372 
00373         // String fuellen
00374         while (m_rxBuffer.size() > 0)
00375         {
00376                 // Es sind noch Daten im Puffer
00377                 c = m_rxBuffer.front();
00378                 m_rxBuffer.pop_front();
00379                 if (c == delimiter)
00380                 {
00381                         // Trennzeichen gefunden - wir sind fertig!
00382                         outString = m_rxString;
00383                         m_rxString.clear();
00384                         break;
00385                 }
00386                 m_rxString += c;
00387         }
00388 
00389         // Ueberlauf der Ausgabe?
00390         if (m_rxString.length() > maxStringLength)
00391         {
00392                 if (m_longStringWarningPrinted == false)
00393                 {
00394                         // Die lange Version
00395                         printWarning("Receive-String has excessive length (" + toString(m_rxString.length()) +" bytes). Clearing string. On serial devices, incorrect bitrate settings may cause this behaviour.");
00396                         m_longStringWarningPrinted = true;
00397                 }
00398                 else
00399                 {
00400                         // Die Kurzfassung
00401                         printWarning("Receive-String has excessive length (" + toString(m_rxString.length()) +" bytes). Clearing string.");
00402                 }
00403                 m_rxString.clear();
00404         }
00405 
00406         // Textmeldung
00407         if ((m_beVerbose == true) && (outString.length() > 0))
00408         {
00409                 printInfoMessage("Tcp::readString: Returning string: " + outString, true);
00410         }
00411 
00412         return outString;
00413 }
00414 
00415 


libsick_ldmrs
Author(s): SICK AG , Martin Günther , Jochen Sprickerhof
autogenerated on Thu Jun 6 2019 21:02:36