Ich habe einen TCP
Server, der neue Verbindungen behandelt, wenn es eine neue Verbindung gibt, werden zwei Threads erstellt (std::thread
, getrennt).boost :: asio schreiben: Gebrochenes Rohr
void Gateway::startServer(boost::asio::io_service& io_service, unsigned short port) {
tcp::acceptor TCPAcceptor(io_service, tcp::endpoint(tcp::v4(), port));
bool UARTToWiFiGatewayStarted = false;
for (;;) { std::cout << "\nstartServer()\n";
auto socket(std::shared_ptr<tcp::socket>(new tcp::socket(io_service)));
/*!
* Accept a new connected WiFi client.
*/
TCPAcceptor.accept(*socket);
socket->set_option(tcp::no_delay(true));
// This will set the boolean `Gateway::communicationSessionStatus` variable to true.
Gateway::enableCommunicationSession();
// start one thread
std::thread(WiFiToUARTWorkerSession, socket, this->SpecialUARTPort, this->SpecialUARTPortBaud).detach();
// start the second thread
std::thread(UARTToWifiWorkerSession, socket, this->UARTport, this->UARTbaud).detach();
}
}
Der erste von zwei Arbeiter Funktionen wie folgt aussehen (hier lese ich die gemeinsame Buchse verwenden):
void Gateway::WiFiToUARTWorkerSession(std::shared_ptr<tcp::socket> socket, std::string SpecialUARTPort, unsigned int baud) {
std::cout << "\nEntered: WiFiToUARTWorkerSession(...)\n";
std::shared_ptr<FastUARTIOHandler> uart(new FastUARTIOHandler(SpecialUARTPort, baud));
try {
while(true == Gateway::communicationSessionStatus) { std::cout << "WiFi->UART\n";
unsigned char WiFiDataBuffer[max_incoming_wifi_data_length];
boost::system::error_code error;
/*!
* Read the TCP data.
*/
size_t length = socket->read_some(boost::asio::buffer(WiFiDataBuffer), error);
/*!
* Handle possible read errors.
*/
if (error == boost::asio::error::eof) {
// this will set the shared boolean variable from "true" to "false", causing the while loop (from the both functions and threads) to stop.
Gateway::disableCommunicationSession();
break; // Connection closed cleanly by peer.
}
else if (error) {
Gateway::disableCommunicationSession();
throw boost::system::system_error(error); // Some other error.
}
uart->write(WiFiDataBuffer, length);
}
}
catch (std::exception &exception) {
std::cerr << "[APP::exception] Exception in thread: " << exception.what() << std::endl;
}
std::cout << "\nExiting: WiFiToUARTWorkerSession(...)\n";
}
und die zweite (hier schreibe ich die Thread-shared mit Buchse):
void Gateway::UARTToWifiWorkerSession(std::shared_ptr<tcp::socket> socket, std::string UARTport, unsigned int baud) {
std::cout << "\nEntered: UARTToWifiWorkerSession(...)\n";
/*!
* Buffer used for storing the UART-incoming data.
*/
unsigned char UARTDataBuffer[max_incoming_uart_data_length];
std::vector<unsigned char> outputBuffer;
std::shared_ptr<FastUARTIOHandler> uartHandler(new FastUARTIOHandler(UARTport, baud));
while(true == Gateway::communicationSessionStatus) { std::cout << "UART->WiFi\n";
/*!
* Read the UART-available data.
*/
auto bytesReceived = uartHandler->read(UARTDataBuffer, max_incoming_uart_data_length);
/*!
* If there was some data, send it over TCP.
*/
if(bytesReceived > 0) {
boost::asio::write((*socket), boost::asio::buffer(UARTDataBuffer, bytesReceived));
std::cout << "\nSending data to app...\n";
}
}
std::cout << "\nExited: UARTToWifiWorkerSession(...)\n";
}
Zum Stoppen dieser zwei Threads ich folgendes tun: von der WiFiToUARTWorkerSession(...)
Funktion, wenn die read(...)
ausfällt (es gibt einen Fehler wie boost::asio::error::eof
, oder irgendein anderer Fehler) Ich setze den booleschen Gateway::communicationSessionStatus
Schalter (der von den beiden Funktionen (global) geteilt wird) auf false
, auf diese Weise sollten die Funktionen zurückkehren, und die Threads sollten anmutig beendet werden.
Wenn ich zum ersten Mal anschließen, das funktioniert gut, aber wenn ich von dem Server bin Abklemmen der Ausführungsablauf von den WiFiToUARTWorkerSession(...)
geht durch else if (error)
Zustand, setzt sich die while
Bedingung Variable false
und dann es wirft boost::system::system_error(error)
(was eigentlich Connection reset by peer
bedeutet).
Dann, wenn ich versuche, wieder zu verbinden, habe ich die folgende Ausnahme, und das Programm endet:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >'
what(): write: Broken pipe
Was könnte das Problem sein?
EDIT: Von dem, was ich über diesen Fehler gefunden, so scheint es, dass ich write(...)
nach der Client die Verbindung trennt, sondern, wie dies möglich sein könnte?
EDIT2: Ich habe den Code noch debugged und es scheint, dass ein Thread (auf das läuft die UARTToWifiWorkerSession(...)
-Funktion) wird nicht tatsächlich zu beenden (weil es eine Blockierung read(...)
Funktionsaufruf bei dem die Ausführung Fluss stoppt). Auf diese Weise wird ein Thread hängen bleiben, bis einige Daten von der read(...)
-Funktion empfangen werden, und wenn ich die Verbindung wieder herstelle, werden zwei weitere Threads erstellt, was einige Datenprobleme verursacht.
Kann mir jemand bestätigen, dass dies das Problem sein könnte?
so ist das Problem, mit dem Klienten Verbindung mit dem Server, richtig? Und Sie haben nicht die Client-Seite des Codes geschrieben. Von was ich denke, ist das, was Sie versuchen zu machen eine Verbindung von der gleichen Buchse, ohne sie zuerst zu schließen. – Arunmu
@Arunmu Ich habe den Code nicht von der Client-Seite, aber was denkst du, wäre das mit dem Client falsch? Und was meinst du damit, dass ich die gleiche Steckdose benutze?Für jede neue Verbindung gibt es einen neuen Socket. –
'Wenn ich versuche, mich wieder zu verbinden..' wo passiert das? Client-Seite oder Server-Seite? – Arunmu