I want to use boost asio sockets to send a message from the server to the client and then print it out to the client terminal. I am trying to send the message "hello". It doesn't work. How can i fix this?
Thanks!
client:
#include <boost/asio.hpp>
#include <iostream>
#include <string>
using namespace std;
int main (int argc, char* argv[]) {
try {
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver::query query("localhost", "41005");
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::iterator destination = resolver.resolve(query);
boost::asio::ip::tcp::resolver::iterator end ;
boost::asio::ip::tcp::endpoint endpoint;
while ( destination != end ) {
endpoint = *destination++;
std::cout<<endpoint<<std::endl;
}
boost::asio::ip::tcp::socket socket(io_service);
socket.connect(endpoint);
boost::array< char, 128 > buf;
boost::system::error_code error;
std::size_t length = boost::asio::read(socket, boost::asio::buffer(buf, 512), boost::asio::transfer_all(), error);
cout << length;
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
server:
#include <boost/asio.hpp>
#include <iostream>
#include <string>
using namespace std;
int main () {
try {
boost::asio::io_service io_service;
boost::asio::ip::tcp::acceptor acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 41005));
for (; ;) {
std::cout<<"Listening to"<<std::endl;
boost::asio::ip::tcp::socket socket(io_service);
acceptor.accept(socket);
std::string message = "hello";
boost::system::error_code ignored_error;
boost::asio::write(socket, boost::asio::buffer(message), boost::asio::transfer_all(), ignored_error);
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
classic error: the "acceptor.accept" method is a blocking call, so the hello part is never called.
Our COut friend would help you, as allways:
...
std::cout<<"Sending hello"<
Related
I was going through the boost asio tutorial trying to learn how to use their networking library. I implemented the example daytime client/server which is here (this is only the server). When running both the client and server I get can't allocate region of size mach_vm_map(size=7597121102135848960).
I have no idea why this is happening.
server:
#include <ctime>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
std::string make_daytime_string() {
using namespace std;
time_t now = time(NULL);
return ctime(&now);
}
int main() {
try {
boost::asio::io_service io;
tcp::acceptor acceptor(io);
tcp::endpoint endpoint(tcp::v4(), 13);
acceptor.open(endpoint.protocol());
acceptor.set_option(tcp::acceptor::reuse_address(true));
acceptor.bind(endpoint); // throwing error here
acceptor.listen();
for(;;) {
tcp::socket socket(io);
acceptor.accept(socket);
std::string message = make_daytime_string();
boost::system::error_code ignore_error;
boost::asio::write(socket, boost::asio::buffer(message), ignore_error);
}
}
catch(std::exception& e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
client:
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
int main(int argc, char ** argv) {
try {
if(argc != 2) {
std::cerr << "Usage: client <host>" << std::endl;
return 1;
}
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query(argv[1], "daytime");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator); // error here
for(;;) {
boost::array<char, 128> buf;
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), error);
if(error == boost::asio::error::eof)
break;
else if(error)
throw boost::system::system_error(error);
std::cout.write(buf.data(), len);
}
}
catch(std::exception& e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
The error is basically the same for both with only a different size:
error:
sserver(14988,0x7fffdc3283c0) malloc: *** mach_vm_map(size=7597121102135848960) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
sserver(14988,0x7fffdc3283c0) malloc:
*** error for object 0x7373696d72655022: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
[1] 14988 abort ./sserver
I anyone know how to fix this I would greatly appreciate it. I should note that I am compiling with g++ 6.1.0 and boost 1.60.02.
I've been trying to modify boost's daytime server/client example to run in 2 threads as below but it didn't work:
#include <ctime>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
using boost::asio::ip::tcp;
std::string make_daytime_string()
{
using namespace std; // For time_t, time and ctime;
time_t now = time(0);
return ctime(&now);
}
void ServerThread()
{
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 13));
for (;;)
{
std::cout << "why?";
tcp::socket socket(io_service);
acceptor.accept(socket);
std::string message = make_daytime_string();
boost::system::error_code ignored_error;
boost::asio::write(socket, boost::asio::buffer(message),
boost::asio::transfer_all(), ignored_error);
}
}
void ClientThread()
{
try
{
boost::asio::io_service io_service;
std::string hostString;
std::cout << "Please enter the host: ";
std::cin >> hostString;
tcp::resolver resolver(io_service);
tcp::resolver::query query(hostString, "daytime");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
int main()
{
boost::thread s(&ServerThread);
boost::thread c(&ClientThread);
c.join();
s.join();
return 0;
}
The two threads run immediately one after another and will not process correctly. I guess I need to do something along the line of a fork? Please help telling me what's wrong with the code, thank you.
In your client, you left out the section of code that receives the data. Put this in after connect:
for (;;)
{
boost::array<char, 128> buf;
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), error);
if (error == boost::asio::error::eof)
break; // Connection closed cleanly by peer.
else if (error)
throw boost::system::system_error(error);
std::cout.write(buf.data(), len);
}
You'll also need to include boost/array.hpp.
I am following the Introduction to Sockets boost::asio tutorial here, called a A synchronous TCP daytime client. I have copied the code exactly, but then moved them into Server.cpp and Client.cpp.
Server.cpp
#include <ctime>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
std::string make_daytime_string()
{
std::time_t now = time(0);
return ctime(&now);
}
int main()
{
try {
std::cout << "Initiating server..." << std::endl;
boost::asio::io_service io;
tcp::acceptor acceptor (io, tcp::endpoint(tcp::v4(), 8889));
for (;;) {
tcp::socket socket (io);
acceptor.accept(socket);
std::string message = make_daytime_string();
boost::system::error_code ignored_error;
boost::asio::write(socket, boost::asio::buffer(message), ignored_error);
}
}
catch (std::exception & e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
Client.cpp
#include <boost/array.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
int main(int argc, char * argv[])
{
boost::asio::io_service io;
// Daytime
try {
if (argc != 2) {
std::cerr << "Usage: client <host>" << std::endl;
return 1;
}
tcp::resolver resolver (io);
tcp::resolver::query query (argv[1], "daytime");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::socket socket (io);
boost::asio::connect(socket, endpoint_iterator);
for (;;) {
boost::array<char, 128> buffer;
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buffer), error);
if (error == boost::asio::error::eof) {
break; // Connection closed cleanly by peer.
}
else if (error) {
throw boost::system::system_error(error); // Some other error.
}
std::cout.write(buffer.data(), len);
}
}
catch (std::exception & e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
First I run the server:
$ ./server
Initiating server...
Then I run the client:
$ ./client localhost
connect: Connection refused
Since I am brand new to sockets and boost, unfortunately I am stuck on finding a solution to this connection refused error message.
Your server is running on port 8889.
Your client connects on port 13 (a.k.a. "daytime").
This will not work. For the obvious reason.
Note if you do decide to run the server on port 13, you need administrative privileges for that.
Hey guys, i'm a newbie to async-programming, this is probably a stupid question, but it indeed drove me crazy!!
Here's the code (it just modified a bit from boost.asio's sample):
server.cpp:
class tcp_server
{
public:
tcp_server(boost::asio::io_service& io_service)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), 10000)),limit(0)
{
start_accept();
}
private:
void start_accept()
{
while(1)
{
if(limit <= 10)
{
std::cout << limit << std::endl;
break;
}
}
tcp::socket* socket = new tcp::socket(acceptor_.io_service());
acceptor_.async_accept(*socket,
boost::bind(&tcp_server::handle_accept, this, boost::asio::placeholders::error));
}
void handle_accept(const boost::system::error_code& error)
{
if (!error)
{
++limit ;
start_accept();
}
}
tcp::acceptor acceptor_;
int limit;
};
int main()
{
try
{
boost::asio::io_service io_service;
tcp_server server(io_service);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
client.cpp:
int main(int argc, char* argv[])
{
int i = 0;
while(1)
{
try
{
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query("127.0.0.1", "10000");
tcp::resolver::iterator endpoint_iterator =resolver.resolve(query);
tcp::endpoint endpoint = *endpoint_iterator;
tcp::socket socket(io_service);
socket.close();
socket.connect(endpoint);
std::cout << i++ << std::endl;
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
return 0;
}
I just wanna limit server to accept 10 client.
However, client cout the error information after it cout "amazing" 210 (never more or less) continuous numbers.
What happend??
I've changed server.cpp a bit. First reconfigured acceptor_ on constructor. Removed while loop, added acceptor_.close();
#include <boost/asio/io_service.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
using namespace boost::asio;
using namespace boost::asio::ip;
class tcp_server
{
public:
tcp_server(boost::asio::io_service& io_service)
: acceptor_(io_service),limit(0)
{
tcp::endpoint endpoint(tcp::v4(), 10000);
acceptor_.open(endpoint.protocol());
acceptor_.bind(endpoint);
acceptor_.listen(1); //accept 1 connection at a time
start_accept();
}
private:
void start_accept()
{
tcp::socket* socket = new tcp::socket(acceptor_.io_service());
acceptor_.async_accept(*socket,
boost::bind(
&tcp_server::handle_accept,
this,
socket,
boost::asio::placeholders::error));
}
void handle_accept(tcp::socket* s, const boost::system::error_code& error)
{
if (!error)
{
++limit;
if (limit < 9)
{
start_accept();
}
else
{
acceptor_.close();
}
}
}
tcp::acceptor acceptor_;
int limit;
};
int main()
{
try
{
boost::asio::io_service io_service;
tcp_server server(io_service);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
I suppose, default acceptor can async_accept 200 connection events at a time. You open a socket and close it from the client side in an infinite loop. As a result you open and close a connection 200 times, but it is still 1 connection, 1 socket.
Capping it to 1 by calling listen(1), would force the acceptor to fire an event. You increase the count, then client closes the connection. This way you correctly count each connection event.
Last note: async io uses 1 thread to process connection events, retrieved data etc... Thus, use of mutexes are not necessary.
I am learning boost/asio ad wrote 2 programs(client and server) from e-book with minor changes.
Basically it should connect to my server.
When i try to connect to outside world(some random http server ) all is good and it works but when i change destination to "localhost:40002" it says invalid argument.
client code:
#include <boost/asio.hpp>
#include <iostream>
int main () {
try {
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver::query query("localhost", 40002);
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::iterator destination = resolver.resolve(query);
boost::asio::ip::tcp::resolver::iterator end ;
boost::asio::ip::tcp::endpoint endpoint;
while ( destination != end ) {
endpoint = *destination++;
std::cout<<endpoint<<std::endl;
}
boost::asio::ip::tcp::socket socket(io_service);
socket.connect(endpoint);
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
i did "netstat -l" and it showed that i am truly listening to my port so server i think works to but never less they don't connect
server code:
#include <boost/asio.hpp>
#include <iostream>
#include <string>
#include <ctime>
std::string time_string()
{
using namespace std;
time_t now = time(0);
return ctime(&now);
}
int main () {
try {
boost::asio::io_service io_service;
boost::asio::ip::tcp::acceptor acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 40002));
for (; ;) {
std::cout<<"Listening to"<<std::endl;
boost::asio::ip::tcp::socket socket(io_service);
acceptor.accept(socket);
std::string message = time_string();
boost::system::error_code ignored_error;
boost::asio::write(socket, boost::asio::buffer(message), boost::asio::transfer_all(), ignored_error);
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
Can someone hint why connection doesn't happen
The second parameter to ip::tcp::resolver::query is the service name, not a port number:
boost::asio::ip::tcp::resolver::query query("localhost", 40002);
should be
boost::asio::ip::tcp::resolver::query query("localhost", "40002");
fyi, when I compiled your code on my system it failed:
resolve.cc: In function ‘int main()’:
resolve.cc:7: error: invalid conversion from ‘int’ to ‘boost::asio::ip::resolver_query_base::flags’
resolve.cc:7: error: initializing argument 2 of ‘boost::asio::ip::basic_resolver_query<InternetProtocol>::basic_resolver_query(const std::string&, boost::asio::ip::resolver_query_base::flags) [with InternetProtocol = boost::asio::ip::tcp]’
I'm surprised it compiled for you.