Hi Igor, Thanks for replying. I may oversimplify my original code in the post, but this piece of code can run and read data from the port. The only problem is unstable. Here is my original code modify from a previous version posted on this board. Again this program can successfully read data from a third part device (which writes data to the RS232 port at certain sampling frequency), but just unstable some times. I know you are a big guy in this discussing board, any suggestions/comments for my debugging? Thanks a lot! -shunguang //------------------ File: test_Rs232Client.cpp ----------------------- #include <stdio.h> #include <conio.h> #include <iostream> #include "Rs232Client.h" using namespace std; using namespace boost::asio; int main(int argc, char* argv[]) { try{ SerialPortParams params; //default construct setting params boost::asio::io_service io; Rs232Client client(io, params); //todo: write sth to the port to control HMR2300 device //client.write( ... ); client.set_max_cnt( 500 ); client.set_dump_file( "c:\\temp\\t1.txt" ); //read data from port into $m_readBuf$, this will read forever client.read(); io.run(); } catch (std::exception& e) { cerr << "Exception: " << e.what() << "\n"; } return 0; } //------------------ File: SerialPortParams.h ----------------------- /* SerialPortParams.h */ #ifndef SERIAL_PORT_PARAMS_H #define SERIAL_PORT_PARAMS_H #include <string> #include <iostream> #include <boost/bind.hpp> #include <boost/asio.hpp> class SerialPortParams { public: SerialPortParams() :device("COM1") ,baud_rate(9600) ,csize( 8 ) ,flow( boost::asio::serial_port_base::flow_control::software ) ,parity( boost::asio::serial_port_base::parity::none ) ,stopbit( boost::asio::serial_port_base::stop_bits::one ) { } public: std::string device; boost::asio::serial_port_base::baud_rate baud_rate; boost::asio::serial_port_base::character_size csize; boost::asio::serial_port_base::flow_control flow; boost::asio::serial_port_base::parity parity; boost::asio::serial_port_base::stop_bits stopbit; }; #endif //------------------ File: Rs232Client.h ----------------------- /* Rs232Client.h */ #ifndef RS232_CLIENT_H #define RS232_CLIENT_H #include <string> #include <deque> #include <iostream> #include <boost/bind.hpp> #include <boost/asio.hpp> #include <boost/asio/serial_port.hpp> #include <boost/thread.hpp> #include "boost/date_time/posix_time/posix_time.hpp" #include "SerialPortParams.h" #define MAX_READ_BYTES 512 #define BYTE_FMT_STR_LEN 28 class DataRaw { public: DataRaw( const boost::posix_time::ptime &curTime, std::deque<unsigned char> &q, const size_t len ) : m_pt( curTime ) { for ( size_t i=0; i<BYTE_FMT_STR_LEN; ++i ){ m_rawStr[i] = q.front(); q.pop_front(); } } void print() { std::cout << boost::posix_time :: to_simple_string ( m_pt ) << std::endl; for ( size_t i=0; i<BYTE_FMT_STR_LEN; ++i ){ printf( "%c", m_rawStr[i] ); } printf( "\n" ); } void dump_to_file( FILE *fp ) const { if (fp){ std::string str = boost::posix_time::to_simple_string( m_pt ); fprintf( fp, "%s,", str.c_str() ); for ( size_t i=0; i<BYTE_FMT_STR_LEN; ++i ){ fprintf( fp, "%d,", m_rawStr[i] ); } fprintf(fp, "\n"); } } public: boost::posix_time::ptime m_pt; unsigned char m_rawStr[BYTE_FMT_STR_LEN]; }; class Rs232Client { public: Rs232Client(boost::asio::io_service& io_service, const SerialPortParams &p ); virtual ~Rs232Client(); void write(const char msg); // pass the write data to the do_write function via the io service in the other thread void read(); //read data into $m_readMsg$ queue void close(); // call the do_close function via the io service in the other thread bool active(); // return true if the serial port is still active void set_stop_signal() { m_stop = true; } void set_max_cnt( const size_t maxCnt ) { m_maxCnt = maxCnt ; } void set_dump_file( const std::string &str ) { m_dumpedFileName = str; } private: void read_start(); void read_complete(const boost::system::error_code& error, size_t bytes_transferred); void do_write(const char msg); void write_start(); void write_complete(const boost::system::error_code& error); void do_close(const boost::system::error_code& error); void process_data( const size_t bytes_transferred ); void dump_data( const char *file ) const; public: std::vector<DataRaw> m_vRaw; //the raw data with time stamps size_t m_cnt; private: bool m_isActive; // remains true while this object is still operating boost::asio::io_service& m_ioService; // the main IO service that runs this connection boost::asio::serial_port m_serialPort; // the serial port this instance is connected to unsigned char m_readMsg[MAX_READ_BYTES];// one time data read from the RS232 port by async_read_some() std::deque<unsigned char> m_writeBuf; // buffered data to write to the port std::deque<unsigned char> m_readBuf; // buffered data reading from the port bool m_stop; // stop communication if this flag is true size_t m_maxCnt; //the maximum # of cnt to stop reading/quiting std::string m_dumpedFileName; }; #endif //------------------ File: Rs232Client.cpp ----------------------- /* Rs232Client.cpp To end the application, send Ctrl-C on standard input */ #include "Rs232Client.h" using namespace std; using namespace boost; Rs232Client :: Rs232Client(boost::asio::io_service& io, const SerialPortParams &p ) : m_isActive( true ) , m_stop ( false ) , m_ioService( io ) , m_serialPort( io, p.device.c_str() ) , m_cnt( 0 ) , m_maxCnt( 0 ) , m_dumpedFileName("") { if ( !m_serialPort.is_open() ) { cerr << "Failed to open serial port\n"; return; } m_serialPort.set_option( p.baud_rate ); m_serialPort.set_option( p.csize ); m_serialPort.set_option( p.flow ); m_serialPort.set_option( p.parity ); m_serialPort.set_option( p.stopbit ); //clear internal data queues m_writeBuf.clear(); m_readBuf.clear(); } Rs232Client::~Rs232Client() { if (m_isActive){ close(); } } void Rs232Client :: read() // pass the write data to the do_write function via the io service in the other thread { printf("read() called \n"); read_start(); } void Rs232Client :: write(const char msg) // pass the write data to the do_write function via the io service in the other thread { m_ioService.post(boost::bind(&Rs232Client::do_write, this, msg)); } void Rs232Client ::close() // call the do_close function via the io service in the other thread { m_ioService.post(boost::bind(&Rs232Client::do_close, this, boost::system::error_code())); } bool Rs232Client ::active() // return true if the socket is still active { return m_isActive; } void Rs232Client :: read_start() { // Start an asynchronous read and call read_complete when it completes or fails m_serialPort.async_read_some( boost::asio::buffer(m_readMsg, MAX_READ_BYTES), boost::bind( &Rs232Client::read_complete, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred) ); } void Rs232Client :: read_complete(const boost::system::error_code& error, size_t bytes_transferred) { // the asynchronous read operation has now completed or failed and returned an error printf("%%%%%%%\n"); if (!error && !m_stop ){ // read completed, so push the data into queue process_data( bytes_transferred ); //start waiting for another asynchronous read again read_start(); //cnt the # of reading operations ++m_cnt; if ( m_cnt>m_maxCnt ){ m_stop = true; } } else{ do_close(error); } } void Rs232Client :: dump_data( const char *file ) const { size_t n = m_vRaw.size(); FILE *fp=fopen( file, "w" ); if ( fp== NULL ) { return; } fprintf( fp, "nSamples=%d\n", n ); vector<DataRaw>::const_iterator it = m_vRaw.begin(); for ( ; it != m_vRaw.end(); ++it ){ it->dump_to_file( fp ); } fclose( fp ); } void Rs232Client :: process_data( const size_t bytes_transferred ) { //1. write reading data into $m_readBuf$ //printf("%d,", bytes_transferred ); for ( size_t i=0; i<bytes_transferred; ++i ){ m_readBuf.push_back( m_readMsg[i] ); //printf("%d,", m_readMsg[i] ); } //printf("\n"); //2. if there are more than $BYTE_FMT_STR_LEN$ characters in $readBuf$, the move data to $m_vRaw$ while ( m_readBuf.size() >= BYTE_FMT_STR_LEN ){ posix_time::ptime pt( posix_time::second_clock::local_time() ); //copy data from $m_readBuf$ to $raw$, and remove copied data from dequeue DataRaw raw( pt, m_readBuf, BYTE_FMT_STR_LEN ); raw.print(); //store data m_vRaw.push_back( raw ); } } void Rs232Client :: do_write(const char msg) { // callback to handle write call from outside this class bool write_in_progress = !m_writeBuf.empty(); // is there anything currently being written? printf( "do_write() called, write_in_progress=%d\n", write_in_progress ); m_writeBuf.push_back(msg); // store in write buffer if (!write_in_progress) // if nothing is currently being written, then start write_start(); } void Rs232Client :: write_start(void) { // Start an asynchronous write and call write_complete when it completes or fails boost::asio::async_write(m_serialPort, boost::asio::buffer(&m_writeBuf.front(), 1), boost::bind(&Rs232Client::write_complete, this, boost::asio::placeholders::error)); } void Rs232Client :: write_complete(const boost::system::error_code& error) { // the asynchronous read operation has now completed or failed and returned an error if (!error) { // write completed, so send next write data m_writeBuf.pop_front(); // remove the completed data if (!m_writeBuf.empty()) // if there is anthing left to be written write_start(); // then start sending the next item in the buffer } else{ do_close(error); } } // something has gone wrong, so close the socket & make this object inactive void Rs232Client :: do_close(const boost::system::error_code& error) { if( ! m_dumpedFileName.empty() ){ dump_data(m_dumpedFileName.c_str() ); } //if this call is the result of a timer cancel() if (error == boost::asio::error::operation_aborted) { return; // ignore it because the connection cancelled the timer } if (error) { cerr << "Error: " << error.message() << endl; // show the error message } else { cout << "Error: Connection did not succeed.\n"; } m_serialPort.close(); m_isActive = false; } -- View this message in context: http://boost.2283326.n4.nabble.com/boost-io-service-run-never-returns-tp4649... Sent from the Boost - Users mailing list archive at Nabble.com.