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


sick_scan
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Tue Jul 9 2019 05:05:35