I am using c++ boost asio for making a server client application.
I followed the guide lines from here.
And I am still wondering why I get the following result:
./server #ok
./client # error
bind: Address already in use
server.cpp:
#include <ctime>
#include <iostream>
#include <stdio.h>
#include <string>
#include <boost/array.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::udp;
struct UDP_Message
{
double number;
};
int main()
{
try
{
boost::asio::io_service io_service;
udp::socket socket(io_service, udp::endpoint(udp::v4(), config::udp_port));
UDP_Message message;
message.number=0;
for (;;)
{
udp::endpoint remote_endpoint;
message.number=message.number+0.001;
boost::system::error_code ignored_error;
socket.send_to(boost::asio::buffer(&message,sizeof(message)),
remote_endpoint, 0, ignored_error);
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
client.cpp:
#include <ctime>
#include <iostream>
#include <stdio.h>
#include <string>
#include <boost/array.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::udp;
namespace config
{
const unsigned short udp_port=1414;
}
struct UDP_Message
{
double number;
};
int main()
{
try
{
boost::asio::io_service io_service;
boost::asio::socket_base::reuse_address option(true);
udp::socket socket(io_service, udp::v4());
socket.set_option(option);
socket.bind(udp::endpoint(udp::v4(), config::udp_port));
UDP_Message message;
for (;;)
{
boost::array<char, 1> recv_buf;
udp::endpoint remote_endpoint;
boost::system::error_code error;
socket.receive_from(boost::asio::buffer(recv_buf),
remote_endpoint, 0, error);
if (error && error != boost::asio::error::message_size)
throw boost::system::system_error(error);
std::memcpy(&message,recv_buf.data(),sizeof(message));
std::cout<<message.number<<std::endl;
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
You are trying to bind both your client and server to the same port, udp_port=1414. This you can not do.
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 tried to create an tcp-server with the boost libs. I basically took example code from boost(the whole code was in 1 file there) and split it up into a class.
Seems like something went wrong there and i dont really know whats missing.
The main error is at the end of "tcp_server.cpp" i put the error message into a comment there. It looks like he doesnt know the function session(at least thats how i interpreted it), i get the same error with "tcp_server::session" and "this->session".
The second thing is an error i get from "e.what()"(cannot resolve identifer what). It worked in the example code and i didnt change anything at the exceptions.
Thanks in advance.
tcp_server.h
#include <cstdlib>
#include <iostream>
#include <exception>
#include <boost/bind.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
using boost::asio::ip::tcp;
class tcp_server
{
public:
typedef boost::shared_ptr<tcp::socket> socket_ptr;
tcp_server();
~tcp_server();
void server(boost::asio::io_service&);
private:
const short port = 8888;
const int max_length = 1024;
void session(socket_ptr);
};
tcp_server.cpp
#include "tcp_server.h"
tcp_server::tcp_server()
{
}
tcp_server::~tcp_server()
{
}
void tcp_server::session(socket_ptr sock)
{
try
{
for (;;)
{
char data[max_length];
boost::system::error_code error;
size_t length = sock->read_some(boost::asio::buffer(data), 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.
boost::asio::write(*sock, boost::asio::buffer(data, length));
}
}
catch (std::exception& e)
{
std::cerr << "Exception in thread: " << e.what() << "\n"; //
}
}
void tcp_server::server(boost::asio::io_service& io_service)
{
tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
for (;;)
{
socket_ptr sock(new tcp::socket(io_service));
a.accept(*sock);
boost::thread t(boost::bind(session, sock)); //error: no matching function for call to ‘bind(<unresolved overloaded function type>, tcp_server::socket_ptr&)’`
}
}
main.cpp
#include "tcp_server.h"
int main() {
tcp_server server;
try
{
boost::asio::io_service io_service;
server.server(io_service);
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
You cannot bind the non-static member function tcp_server::session because it cannot be called without an object instance, which is not available to the bind.
You can however make tcp_server::session static (in tcp_header.h) to fix this:
static void session(socket_ptr);
Edit:
You can bind session as non-static member using:
boost::thread t(boost::bind(&tcp_server::session, this, sock));
How can I connect to my domain through my server, so that I can "host" it?
I've tried changing the code snippet below to match the IP with my domain's name, but a exception is caught saying that a invalid argument was supplied, I assumed I should resolve the domain name, get the IP and use the IP I got and not the one in the code snippet below, but it seems like I'm connecting to my external IP, and this doesn't let me host the server, as it says the machine actively refused the connection.
That's the code snippet:
boost::asio::ip::tcp::acceptor acceptor(service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string("192.168.1.3"), 8001));
That's the full code:
Main.cpp
#include "Server.h"
#include <string>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
int main()
{
Server server;
boost::thread([&server] {
server.handleConnections();
}).join();
return 0;
}
Server.h
#ifndef SERVER_H
#define SERVER_H
#include <string>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
class Server
{
private:
boost::asio::io_service service;
boost::asio::ip::tcp::socket sock;
protected:
public:
Server() : service(), sock(service) {
}
~Server() {
}
void handleConnections();
};
#endif
Server.cpp
#include "Server.h"
void Server::handleConnections() {
boost::system::error_code err;
try {
boost::asio::ip::tcp::acceptor acceptor(service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string("192.168.1.3"), 8001));
std::cout << acceptor.local_endpoint(err) << std::endl;
while (true) {
sock = boost::asio::ip::tcp::socket(service);
boost::system::error_code errCode;
acceptor.accept(this->sock, acceptor.local_endpoint(), errCode);
boost::asio::write(sock, boost::asio::buffer("Olá"), errCode);
}
this->sock.close();
}
catch (std::exception & e)
{
std::cout << e.what();
}
}
Firstly
acceptor.accept(this->sock, acceptor.local_endpoint(), errCode);
The documentation says:
This function is used to accept a new connection from a peer into the given socket, and additionally provide the endpoint of the remote peer. The function call will block until a new connection has been accepted successfully or an error occurs.
You ... pass the acceptor's local endpoint as the endpoint to receive the peer's remote endpoint (I'm surprised if that compiles). That makes little sense. I suggest you don't need to know the remote endpoint¹:
acceptor.accept(this->sock, errCode);
Secondly, you've bound to the loopback adaptor:
boost::asio::ip::tcp::acceptor acceptor(service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string("192.168.1.3"), 8001));
This directly implies you cannot access it from the network². Change it to be NIC-agnostic:
tcp::acceptor acceptor(service, tcp::endpoint(ip::address(), 8001));
¹ you can usually get it from the socket later using socket_->remote_endpoint() unless the socket has become invalid (e.g. closed)
² unless you implement some funky routing/tunneling logic, which is far stretch
UPDATE
Self contained demo with error handling:
Live On Coliru
#include <iostream>
#include <boost/asio.hpp>
class Server
{
boost::asio::io_service service;
public:
void handleConnections()
{
using namespace boost::asio;
boost::system::error_code err;
try {
ip::tcp::acceptor acceptor(service, ip::tcp::endpoint(ip::address(), 6768));
std::cout << acceptor.local_endpoint(err) << std::endl;
while (!err) {
ip::tcp::socket sock(service);
if ( !acceptor.accept(sock, err)
&& !write(sock, buffer("Olá"), err)
&& !sock.close(err))
{
std::cout << "Error in connection: " << err << " " << err.message() << "\n";
}
}
} catch (std::exception & e) {
std::cout << e.what();
}
}
};
#include <boost/thread.hpp>
int main() {
Server server;
boost::thread([&server] { server.handleConnections(); }).join();
}
Output:
$ ./a.out&
0.0.0.0:6768
$ while sleep 1; do nc 127.0.0.1 6768; done
OláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOláOlá
I'm currently working with Boost::Asio to do a basic Read/Write server, I have a little problem when it comes to the usage of the async_read function of the library.
Here's my code snippet :
main.cpp :
#include <ctime>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include "TCPServer.hpp"
#include "TCPConnection.hpp"
using boost::asio::ip::tcp;
int main()
{
try
{
boost::asio::io_service io_service;
TCPServer server(io_service);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
TCPServer.hpp :
#ifndef TCPSERVER_HPP_
#define TCPSERVER_HPP_
#include <ctime>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include "TCPConnection.hpp"
using boost::asio::ip::tcp;
class TCPServer
{
private:
tcp::acceptor _acceptor;
public:
TCPServer(boost::asio::io_service& ioService)
: _acceptor(ioService, tcp::endpoint(tcp::v4(), 4040))
{
startAccept();
}
private:
void startAccept()
{
TCPConnection::pointer newConnection =
TCPConnection::create(_acceptor.get_io_service());
_acceptor.async_accept(newConnection->getSocket(),
boost::bind(&TCPServer::handleAccept, this, newConnection,
boost::asio::placeholders::error));
}
void handleAccept(TCPConnection::pointer newConnection, const boost::system::error_code& error)
{
if (!error)
{
newConnection->asyncWrite("JIOLE");
startAccept();
}
}
};
#endif
TCPConnection.hpp :
#ifndef TCPCONNECTION_HPP_
#define TCPCONNECTION_HPP_
#include <ctime>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
class TCPConnection : public boost::enable_shared_from_this<TCPConnection>
{
private:
boost::asio::ip::tcp::socket _socket;
std::string _readMessage;
boost::asio::streambuf _response;
public:
typedef boost::shared_ptr<TCPConnection> pointer;
static pointer create(boost::asio::io_service& ios)
{
return pointer(new TCPConnection(ios));
}
boost::asio::ip::tcp::socket& getSocket()
{
return _socket;
}
void asyncWrite(const std::string &message)
{
boost::asio::async_write(_socket,
boost::asio::buffer(message),
boost::bind(&TCPConnection::handleWrite, shared_from_this(),
boost::asio::placeholders::error));
std::cout << "AsyncWrite" << std::endl;
}
void asyncRead()
{
std::cout << "1st \"asyncRead\"" << std::endl;
boost::asio::async_read(_socket,
_response,
boost::bind(&TCPConnection::handleRead, shared_from_this(),
boost::asio::placeholders::error));
std::cout << "2nd \"asyncRead\"" << std::endl;
}
void close()
{
_socket.close();
}
private:
TCPConnection(boost::asio::io_service &ioS) : _socket(ioS) {}
void handleWrite(const boost::system::error_code& error)
{
std::cout << "Write Handler" << std::endl;
if (!error)
{
asyncRead();
}
//SEE WHAT TO DO IN CASE OF ERROR
}
void handleRead(const boost::system::error_code& error)
{
std::cout << "Read Handler" << std::endl;
if (!error)
{
std::cout << &_response << std::endl;
asyncRead();
}
else
{
std::cout << &error << std::endl;
_socket.close();
}
//CREATE SENDER(RSEPONSE::ERROR)
}
};
#endif
The problem is that my async_read doesn't call the handler. Here is the output :
Output :
AsyncWrite
Write Handler
1st "asyncRead"
2nd "asyncRead"
When I'm writing something on a NetCat Client nothing is being received.
Here what happens when i'm pressing ctrl+C :
Read Handler
0x7fff645f3be0
I don't understand why nothing is received.
The problem is that you did not tell async_read when it should call the handler function. There are two ways to specify this: Either specify the input size after which the handler shall be called or specifiy a delimiter through async_read_until.
In your case, you could use the following:
boost::asio::async_read_until(_socket,
_response,
"\n",
boost::bind(&TCPConnection::handleRead,
shared_from_this(),
boost::asio::placeholders::error)
);
This will call the handler when a newline is sent from the client.
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"<