Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r49483 - in trunk/libs/asio: doc doc/overview example/chat
From: chris_at_[hidden]
Date: 2008-10-29 08:50:59


Author: chris_kohlhoff
Date: 2008-10-29 08:50:58 EDT (Wed, 29 Oct 2008)
New Revision: 49483
URL: http://svn.boost.org/trac/boost/changeset/49483

Log:
Add a new POSIX-specific chat client showing how to use the
posix::stream_descriptor class.

Added:
   trunk/libs/asio/example/chat/posix_chat_client.cpp (contents, props changed)
Text files modified:
   trunk/libs/asio/doc/examples.qbk | 6 ++++++
   trunk/libs/asio/doc/overview/posix.qbk | 3 ++-
   trunk/libs/asio/example/chat/Jamfile | 13 +++++++++++++
   trunk/libs/asio/example/chat/Jamfile.v2 | 1 +
   4 files changed, 22 insertions(+), 1 deletions(-)

Modified: trunk/libs/asio/doc/examples.qbk
==============================================================================
--- trunk/libs/asio/doc/examples.qbk (original)
+++ trunk/libs/asio/doc/examples.qbk 2008-10-29 08:50:58 EDT (Wed, 29 Oct 2008)
@@ -33,6 +33,12 @@
 * [@boost_asio/example/chat/chat_client.cpp]
 * [@boost_asio/example/chat/chat_server.cpp]
 
+The following POSIX-specific chat client demonstrates how to use the
+[link boost_asio.reference.posix__stream_descriptor posix::stream_descriptor]
+class to perform console input and output.
+
+* [@boost_asio/example/chat/posix_chat_client.cpp]
+
 
 [heading Echo]
 

Modified: trunk/libs/asio/doc/overview/posix.qbk
==============================================================================
--- trunk/libs/asio/doc/overview/posix.qbk (original)
+++ trunk/libs/asio/doc/overview/posix.qbk 2008-10-29 08:50:58 EDT (Wed, 29 Oct 2008)
@@ -92,7 +92,8 @@
 
 [link boost_asio.reference.posix__stream_descriptor posix::stream_descriptor],
 [link boost_asio.reference.posix__basic_stream_descriptor posix::basic_stream_descriptor],
-[link boost_asio.reference.posix__stream_descriptor_service posix::stream_descriptor_service].
+[link boost_asio.reference.posix__stream_descriptor_service posix::stream_descriptor_service],
+[link boost_asio.examples.chat Chat example].
 
 [heading Notes]
 

Modified: trunk/libs/asio/example/chat/Jamfile
==============================================================================
--- trunk/libs/asio/example/chat/Jamfile (original)
+++ trunk/libs/asio/example/chat/Jamfile 2008-10-29 08:50:58 EDT (Wed, 29 Oct 2008)
@@ -45,3 +45,16 @@
     <mingw><*><find-library>mswsock
     $(SOCKET_LIBS)
   ;
+
+exe posix_chat_client
+ : <lib>@boost/libs/thread/build/boost_thread
+ <lib>@boost/libs/system/build/boost_system
+ posix_chat_client.cpp
+ : <include>$(BOOST_ROOT)
+ <include>../../../..
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <mingw><*><find-library>ws2_32
+ <mingw><*><find-library>mswsock
+ $(SOCKET_LIBS)
+ ;

Modified: trunk/libs/asio/example/chat/Jamfile.v2
==============================================================================
--- trunk/libs/asio/example/chat/Jamfile.v2 (original)
+++ trunk/libs/asio/example/chat/Jamfile.v2 2008-10-29 08:50:58 EDT (Wed, 29 Oct 2008)
@@ -40,3 +40,4 @@
 
 exe chat_server : chat_server.cpp ;
 exe chat_client : chat_client.cpp ;
+exe posix_chat_client : posix_chat_client.cpp ;

Added: trunk/libs/asio/example/chat/posix_chat_client.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/example/chat/posix_chat_client.cpp 2008-10-29 08:50:58 EDT (Wed, 29 Oct 2008)
@@ -0,0 +1,216 @@
+//
+// posix_chat_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <cstdlib>
+#include <cstring>
+#include <boost/array.hpp>
+#include <boost/bind.hpp>
+#include <boost/asio.hpp>
+#include "chat_message.hpp"
+
+#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+
+using boost::asio::ip::tcp;
+namespace posix = boost::asio::posix;
+
+class posix_chat_client
+{
+public:
+ posix_chat_client(boost::asio::io_service& io_service,
+ tcp::resolver::iterator endpoint_iterator)
+ : socket_(io_service),
+ input_(io_service, ::dup(STDIN_FILENO)),
+ output_(io_service, ::dup(STDOUT_FILENO)),
+ input_buffer_(chat_message::max_body_length)
+ {
+ // Try connecting to the first endpoint.
+ tcp::endpoint endpoint = *endpoint_iterator;
+ socket_.async_connect(endpoint,
+ boost::bind(&posix_chat_client::handle_connect, this,
+ boost::asio::placeholders::error, ++endpoint_iterator));
+ }
+
+private:
+
+ void handle_connect(const boost::system::error_code& error,
+ tcp::resolver::iterator endpoint_iterator)
+ {
+ if (!error)
+ {
+ // Read the fixed-length header of the next message from the server.
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.data(), chat_message::header_length),
+ boost::bind(&posix_chat_client::handle_read_header, this,
+ boost::asio::placeholders::error));
+
+ // Read a line of input entered by the user.
+ boost::asio::async_read_until(input_, input_buffer_, '\n',
+ boost::bind(&posix_chat_client::handle_read_input, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else if (endpoint_iterator != tcp::resolver::iterator())
+ {
+ // That endpoint didn't work, try the next one.
+ socket_.close();
+ tcp::endpoint endpoint = *endpoint_iterator;
+ socket_.async_connect(endpoint,
+ boost::bind(&posix_chat_client::handle_connect, this,
+ boost::asio::placeholders::error, ++endpoint_iterator));
+ }
+ }
+
+ void handle_read_header(const boost::system::error_code& error)
+ {
+ if (!error && read_msg_.decode_header())
+ {
+ // Read the variable-length body of the message from the server.
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
+ boost::bind(&posix_chat_client::handle_read_body, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ close();
+ }
+ }
+
+ void handle_read_body(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ // Write out the message we just received, terminated by a newline.
+ static char eol[] = { '\n' };
+ boost::array<boost::asio::const_buffer, 2> buffers = {{
+ boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
+ boost::asio::buffer(eol) }};
+ boost::asio::async_write(output_, buffers,
+ boost::bind(&posix_chat_client::handle_write_output, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ close();
+ }
+ }
+
+ void handle_write_output(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ // Read the fixed-length header of the next message from the server.
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(read_msg_.data(), chat_message::header_length),
+ boost::bind(&posix_chat_client::handle_read_header, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ close();
+ }
+ }
+
+ void handle_read_input(const boost::system::error_code& error,
+ std::size_t length)
+ {
+ if (!error)
+ {
+ // Write the message (minus the newline) to the server.
+ write_msg_.body_length(length - 1);
+ input_buffer_.sgetn(write_msg_.body(), length - 1);
+ input_buffer_.consume(1); // Remove newline from input.
+ write_msg_.encode_header();
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(write_msg_.data(), write_msg_.length()),
+ boost::bind(&posix_chat_client::handle_write, this,
+ boost::asio::placeholders::error));
+ }
+ else if (error == boost::asio::error::not_found)
+ {
+ // Didn't get a newline. Send whatever we have.
+ write_msg_.body_length(input_buffer_.size());
+ input_buffer_.sgetn(write_msg_.body(), input_buffer_.size());
+ write_msg_.encode_header();
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(write_msg_.data(), write_msg_.length()),
+ boost::bind(&posix_chat_client::handle_write, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ close();
+ }
+ }
+
+ void handle_write(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ // Read a line of input entered by the user.
+ boost::asio::async_read_until(input_, input_buffer_, '\n',
+ boost::bind(&posix_chat_client::handle_read_input, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else
+ {
+ close();
+ }
+ }
+
+ void close()
+ {
+ // Cancel all outstanding asynchronous operations.
+ socket_.close();
+ input_.close();
+ output_.close();
+ }
+
+private:
+ tcp::socket socket_;
+ posix::stream_descriptor input_;
+ posix::stream_descriptor output_;
+ chat_message read_msg_;
+ chat_message write_msg_;
+ boost::asio::streambuf input_buffer_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: posix_chat_client <host> <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_service io_service;
+
+ tcp::resolver resolver(io_service);
+ tcp::resolver::query query(argv[1], argv[2]);
+ tcp::resolver::iterator iterator = resolver.resolve(query);
+
+ posix_chat_client c(io_service, iterator);
+
+ io_service.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
+
+#else // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+int main() {}
+#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk