On the first run - bind successful, when i restart program - error 10048( address already use)
without calling close and shutdown - restart everything is fine
boost::asio::io_service _ioService;
boost::asio::ip::tcp::socket _socket(_ioService);
boost::system::error_code err;
_socket.open(boost::asio::ip::tcp::v4(), err);
if (err.value())
{
cout<<err.value()<<endl;
cout << err.message() << endl;
}
_socket.bind(boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::from_string("127.0.0.1"), 1276), err);
cout << err.value() << endl;
if (err.value())
{
cout << err.value() << endl;
cout << err.message() << endl;
}
_socket.connect(boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::from_string("127.0.0.1"), 1500), err);
if (err.value())
{
cout << err.value() << endl;
cout << err.message() << endl;
}
_socket.shutdown(_socket.shutdown_both);
_socket.close(err);
if (err.value())
{
cout << err.value() << endl;
cout << err.message() << endl;
}
The problem is that, the socket may have entered a TIME-WAIT state. See Error: Address already in use while binding socket with address but the port number is shown free by `netstat`
You can set the option to reuse the address: that should prevent such TIME-WAIT See this explanation and a more comprehensive version here.
In Boost.ASIO, you can do it this way:
//Add this
boost::asio::socket_base::reuse_address reuse_address_option(true);
m_socket.set_option(reuse_address_option);
m_socket.bind(boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::from_string("127.0.0.1"), 1250), err);
EDIT
After digging through the source code of acceptor there is an example in the source documentation, reproduced here
// #par Example
// Opening a socket acceptor with the SO_REUSEADDR option enabled:
// #code
boost::asio::ip::tcp::acceptor acceptor(io_service);
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
acceptor.open(endpoint.protocol());
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
acceptor.bind(endpoint);
acceptor.listen();
Related
So I am trying to make a telnet client that connects to some address part for work and part for Boost::Asio learning purpose.
My small project has three handlers:
Resolve handler:
void resolverHandler(const boost::system::error_code& ec, ip::tcp::resolver::iterator iter) {
if (ec) {
cout << "Resolved failed with message: " << ec.message() << endl;
}
else {
ip::tcp::endpoint endpoint = *iter;
cout << "Connection to: " << endpoint.address() << ":" << endpoint.port() << endl;
tcpSocket.async_connect(endpoint, connectHandler);
}
}
Connect handler
void connectHandler(const boost::system::error_code& ec) {
if (ec) {
cout << "Connect failed with message: " << ec.message() << endl;
}
else {
cout << "Connection established" << endl;
tcpSocket.async_read_some(buffer(_data), readHandler);
}
}
Read handler:
void readHandler(const boost::system::error_code& ec, size_t amountOfBytes) {
if (ec) {
cout << "Read failed with message: " << ec.message() << endl;
}
else {
cout << amountOfBytes << endl;
cout << _data.data() << endl;
tcpSocket.async_read_some(buffer(_data), readHandler);
}
}
And this is my main function:
io_service ioservice;
ip::tcp::resolver resolver(ioservice);
ip::tcp::socket tcpSocket(ioservice);
array<char, 16> _data;
ip::tcp::resolver::query query("192.168.200.200", "23");
int main() {
resolver.async_resolve(query, resolverHandler);
ioservice.run();
return 0;
}
But I always get garbage like this:
Connection to: 192.168.206.226:23
Connection established
15
² ² ²# ²' ²$
I admit that I am new to telnet, but I am not sure why do I get this response ? Not sure if I need to null terminate the data that I receive before printing it, but even like that I have the same response.
Here is the normal response I should receive - tried with Windows Telnet:
Welcome Message (localhost) (ttyp0)
login:
Apreciate if someone has any ideas on what to do.
I am trying to write a simple server that allows multiple clients to connect. When I run my program, I get the following error as output:
[3730] Press [return] to exit.
Listening on: 127.0.0.1:7777
[5d0] Thread Start
Error: system:995 The I/O operation has been aborted because of either a
thread exit or an application request
I think this is because my Client object is falling out of scope, but I'm not entirely sure if this is actually the problem or if there's something else wrong with my code.
ClientNetwork::ClientNetwork(asio::io_service& ios, const asio::ip::tcp::endpoint& edp) : mIOService(ios), mAcceptor(ios, edp)
{
/*mAcceptor.open(edp.protocol());
mAcceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(false));*/
listen();
}
ClientNetwork::~ClientNetwork()
{
boost::system::error_code ec;
mAcceptor.close(ec);
mConnectionThreads.join_all();
mClients.clear();
std::cout << "KILLING NETWORK" << std::endl;
}
void ClientNetwork::listen()
{
mConnectionThreads.create_thread(boost::bind(&ClientNetwork::connectionThread, this));
Client* c = new Client(mIOService);
mAcceptor.listen(boost::asio::socket_base::max_connections);
mAcceptor.async_accept(*c->getSocket(), boost::bind(&ClientNetwork::handleAccept, this, _1, c));
}
void ClientNetwork::handleAccept(const boost::system::error_code& error, Client* client)
{
if (!error)
{
mClients.push_back(client);
mConnectionThreads.create_thread(boost::bind(&ClientNetwork::connectionThread, this));
std::cout << mConnectionThreads.size() << std::endl;
}
else
{
std::cout << "Error: " << error << " " << error.message() << std::endl;
}
}
This is my main (not sure it's entirely helpful but felt it would be good to include:
int main(int argc, char * argv[])
{
boost::shared_ptr< boost::asio::io_service > io_service(
new boost::asio::io_service
);
boost::shared_ptr< boost::asio::io_service::work > work(
new boost::asio::io_service::work(*io_service)
);
boost::shared_ptr< boost::asio::io_service::strand > strand(
new boost::asio::io_service::strand(*io_service)
);
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id()
<< "] Press [return] to exit." << std::endl;
global_stream_lock.unlock();
/*boost::thread_group worker_threads;
for (int x = 0; x < 2; ++x)
{
worker_threads.create_thread(boost::bind(&WorkerThread, io_service));
}*/
/*boost::shared_ptr< boost::asio::ip::tcp::acceptor > acceptor(
new boost::asio::ip::tcp::acceptor(*io_service)
);
boost::shared_ptr< boost::asio::ip::tcp::socket > sock(
new boost::asio::ip::tcp::socket(*io_service)
);*/
try
{
boost::asio::ip::tcp::resolver resolver(*io_service);
boost::asio::ip::tcp::resolver::query query(
"127.0.0.1",
boost::lexical_cast< std::string >(7777)
);
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
ClientNetwork clientNet(*io_service, endpoint);
global_stream_lock.lock();
std::cout << "Listening on: " << endpoint << std::endl;
global_stream_lock.unlock();
}
catch (std::exception & ex)
{
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id()
<< "] Exception: " << ex.what() << std::endl;
global_stream_lock.unlock();
}
std::cin.get();
//worker_threads.join_all();
return 0;
}
After creating ClientNetwork object and when first an asynchronous operation was started you should run io_service::run method to process handlers in events loop then your program runs until there is at least one asynchronous operation to be executed.
At the end of try scope put io_service->run():
ClientNetwork clientNet(*io_service, endpoint);
global_stream_lock.lock();
std::cout << "Listening on: " << endpoint << std::endl;
global_stream_lock.unlock();
io_service->run();
Without this the destructor of ClientNetwork class is called and mAcceptor is closed with printing this error message
void ClientNetwork::handleAccept (...) {
...
std::cout << "Error: " << error << " " << error.message() << std::endl;
}
Hello I ve been trying to implement a simple server/client app to communicate through UDP socket and understand how UDP works using boost library, my problem is that async_receive is not being invoked or is not getting complete in order to jump on the handler
UDP server:
#include "udp_server.h"
udp_server::udp_server(boost::asio::io_service& io_service, string bind_address, uint16_t bind_port)
: socket_(io_service)
{
cout << "udp_server constructor start" << endl;
boost::shared_ptr<boost::asio::io_service::work> work(
new boost::asio::io_service::work(io_service));
for(int x=0; x<5; ++x)
{
worker_threads.create_thread(boost::bind(&udp_server::WorkerThread, this , boost::ref(io_service)));
}
boost::system::error_code myError;
boost::asio::ip::address IP;
IP = boost::asio::ip::address::from_string(bind_address, myError);
local_udppoint_.address(IP);
cout << "IP Address: " << local_udppoint_.address().to_string() << endl;
local_udppoint_.port(bind_port);
cout << "Port: " << local_udppoint_.port() << endl;
socket_.open(local_udppoint_.protocol(), myError);
std::cout << "Open - " << myError.message() << std::endl;
socket_.bind( local_udppoint_, myError );
std::cout << "Bind - " << myError.message() << std::endl;
udp::endpoint sender_endpoint_;
struct test *request = (struct test *) malloc (sizeof(struct test));
socket_.async_receive_from(
boost::asio::buffer(&request, sizeof(request->type)), sender_endpoint_,
boost::bind(&udp_server::handle_receive_from, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
cout << "udp_server constructor end" << endl;
}
void udp_server::WorkerThread(io_service &io_service_)
{
std::cout << "Thread Start\n";
io_service_.run();
std::cout << "Thread Finish\n";
}
void udp_server::handle_receive_from(const boost::system::error_code& err, size_t bytes_recvd)
{
cout << "udp_server::handle_receive_from enters?" << endl;
if(!err)
{
cout << "no message" << endl;
}
else
{
cout << err.message() << endl;
}
if (!err && bytes_recvd > 0)
{
cout << "All good" << endl;
}
else
{
cout << err.message() << "2" << endl;
}
}
udp_server::~udp_server(void)
{
//io_service.stop();
worker_threads.join_all();
cout << "udp_server::destructor" << endl;
}
Server's Main:
#include "udp_server.h"
int main()
{
try
{
boost::asio::io_service io_service;
//boost::asio::io_service::work work( io_service);
udp_server s(io_service, "127.0.0.1", 4000);
//io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
string a;
cin >> a;
return 0;
}
UDP Client:
#include "udp_client.h"
udp_client::udp_client(boost::asio::io_service& io_service, string send_address, uint16_t send_port)
: io_service_(io_service), socket_(io_service)
{
cout << "udp_client::constructor_start" << endl;
boost::system::error_code myError;
boost::asio::ip::address IP;
IP = boost::asio::ip::address::from_string(send_address, myError);
remote_endpoint_.address(IP);
cout << "IP Address: " << remote_endpoint_.address().to_string() << endl;
remote_endpoint_.port(send_port);
cout << "Port: " << remote_endpoint_.port() << endl;
struct test *request = (struct test *) malloc (sizeof(struct test));
request->type = START_STORAGE;
socket_.async_send_to(boost::asio::buffer(&request, sizeof(request->type)), remote_endpoint_,
boost::bind(&udp_client::start_handler, this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
cout << "udp_client::constructor_end" << endl;
}
void
udp_client::start_handler(const boost::system::error_code&, std::size_t)
{
cout << "udp_client::start_handler()" << endl;
}
udp_client::~udp_client(void)
{
}
Client's main:
#include "udp_client.h"
int main(int argc, char* argv[])
{
try
{
boost::asio::io_service io_service;
udp_client client(io_service, "127.0.0.1", 4000);
io_service.run ();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
string a;
cin >> a;
return 0;
}
As you can see in the outputs below client invoked async_send_to and the message on the handler is being printed but on the server side nothing happens
UDP Server Console output:
udp_server constructor star
Thread Start
Thread Start
Thread Start
Thread Start
Thread Start
IP Address: 127.0.0.1
Port: 4000
Open - The operation completed successfully
Bind - The operation completed successfullyudp_server constructor end
_
UDP Client Console:
udp_client::constructor_start
IP Address: 127.0.0.1
Port: 4000
udp_client::constructor_end
udp_client::start_handler()
Any ideas why async_receive_from is not completed or invoked?
Right off the bat, calling join_all on your listening threads in your destructor is going to lead to undefined behavior. You're trying to keep your server running while it's right in the middle of being destroyed. Don't do this. As an example, running the io_service from these threads, you have handlers that bind to this* that those threads will be hooking into. Inside the destructor, this* is no longer a valid object. In all of your callbacks, you should be checking the error param you were passed to see if it is set.
if(error)
{
std::cout << "Error in MyClass::MyFunc(...): " << error << std::endl;
}
.. to get the errors printed to the console. Guaranteed you're going to see an error from ::bind that such and such is an invalid object.
You should be doing something inside your server main where you're blocking to prevent main from exiting. Move your thread group that runs your server's io_service and the io_service itself outside of the server object. Wrap the io_service with a ::work() object to prevent the io_service from stopping itself when it thinks that it's run out of work (no more connections to process).
Beyond that, the simplest thing to do is point you to the droves of TCP and UDP client and server examples that boost docs provide. http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/examples.html
I'm trying to send a string via SocketSource and SocketSink. But somehow it won't work properly. I simply want to send it from my server to the client. Here's the code:
Server:
CryptoPP::Socket server;
CryptoPP::Socket client;
sockaddr_in client_sadr;
CryptoPP::socklen_t size_sock = sizeof(sockaddr_in);
timeval timev = {3, 0};
std::string test("a simple test");
CryptoPP::Socket::StartSockets();
server.Create(SOCK_STREAM);
server.Bind(4213, NULL);
server.Listen();
server.Accept(client, (sockaddr*)&client_sadr, &size_sock);
std::cout << "Client connected" << std::endl;
while (!client.SendReady(&timev));
CryptoPP::StringSource ss(test, true, new CryptoPP::SocketSink(client));
std::cout << "Data sent" << std::endl;
std::cin.ignore();
client.CloseSocket();
server.CloseSocket();
CryptoPP::Socket::ShutdownSockets();
Client:
CryptoPP::Socket client;
CryptoPP::socklen_t size_sock = sizeof(sockaddr_in);
timeval timev = {3, 0};
std::string test;
Socket::StartSockets();
client.Create(SOCK_STREAM);
client.Connect("127.0.0.1", 4213);
std::cout << "connected" << std::endl;
while (!client.ReceiveReady(&timev));
CryptoPP::SocketSource(client, true, new StringSink(test));
std::cout << test << std::endl;
std::cin.ignore();
client.CloseSocket();
Socket::ShutdownSockets();
What happens now: The connection is established as wished, and the server sends the data, the client receives it and waits at cin.ignore(). But the server seemes to hang up while sending, because it won't print "Data send". It only does this, when the client closes the connection.
My question now is, am I doing something wrong, or is this just the normal behavior of SocketSource and SocketSink and i have to reconnect everytime...
Thanks for your help :)
The following is from test.cpp. It might give you some ideas. I don't recall reading on how to use them (and I've never used them in a program). Its the only place I've ever seen PumpAll2 and non-blocking used.
You might find they work better on Windows than Linux.
void ForwardTcpPort(const char *sourcePortName, const char *destinationHost,
const char *destinationPortName)
{
SocketsInitializer sockInit;
Socket sockListen, sockSource, sockDestination;
int sourcePort = Socket::PortNameToNumber(sourcePortName);
int destinationPort = Socket::PortNameToNumber(destinationPortName);
sockListen.Create();
sockListen.Bind(sourcePort);
setsockopt(sockListen, IPPROTO_TCP, TCP_NODELAY, "\x01", 1);
cout << "Listing on port " << sourcePort << ".\n";
sockListen.Listen();
sockListen.Accept(sockSource);
cout << "Connection accepted on port " << sourcePort << ".\n";
sockListen.CloseSocket();
cout << "Making connection to " << destinationHost << ", port " << destinationPort << ".\n";
sockDestination.Create();
sockDestination.Connect(destinationHost, destinationPort);
cout << "Connection made to " << destinationHost << ", starting to forward.\n";
SocketSource out(sockSource, false, new SocketSink(sockDestination));
SocketSource in(sockDestination, false, new SocketSink(sockSource));
WaitObjectContainer waitObjects;
while (!(in.SourceExhausted() && out.SourceExhausted()))
{
waitObjects.Clear();
out.GetWaitObjects(waitObjects, CallStack("ForwardTcpPort - out", NULL));
in.GetWaitObjects(waitObjects, CallStack("ForwardTcpPort - in", NULL));
waitObjects.Wait(INFINITE_TIME);
if (!out.SourceExhausted())
{
cout << "o" << flush;
out.PumpAll2(false);
if (out.SourceExhausted())
cout << "EOF received on source socket.\n";
}
if (!in.SourceExhausted())
{
cout << "i" << flush;
in.PumpAll2(false);
if (in.SourceExhausted())
cout << "EOF received on destination socket.\n";
}
}
}
So I have code like:
using namespace boost::asio::ip;
using namespace std;
void request_response_loop(boost::asio::ip::tcp::socket& socket)
{
http_request request(socket);
http_response response;
response.body = "<head></head><body><h1>It Rocks!</h1></body>";
response.send(socket);
socket.close();
cout << "connection resolved." << endl;
}
void acceptor_loop(){
boost::asio::io_service io_service;
int m_nPort = 12345;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), m_nPort));
cout << "Waiting for connection..." << endl;
while(true)
{
try
{
tcp::socket socket(io_service);
acceptor.accept(socket);
cout << "connection accepted." << endl;
boost::thread workerThread2(request_response_loop, socket); // here it does not compile because of C2248
}
catch(exception &e)
{
cerr << e.what() << endl; //"The parameter is incorrect" exception
}
}
}
int main()
{
boost::thread workerThread(acceptor_loop);
cin.get();
}
It gives me error:
Error 1 error C2248: boost::noncopyable_::noncopyable::noncopyable: "boost::noncopyable_::noncopyable" boost\asio\basic_io_object.hpp 93
How to make it possible to run my request_response_loop function in another thread that one I use for socket accepting?
To expand on Ben's answer, boost::shared_ptr<> is the usual mechanism here:
void request_response_loop(boost::shared_ptr<tcp::socket> socket)
{
http_request request(*socket);
http_response response;
response.body = "<head></head><body><h1>It Rocks!</h1></body>";
response.send(*socket);
socket->close();
cout << "connection resolved." << endl;
}
void acceptor_loop()
{
boost::asio::io_service io_service;
int m_nPort = 12345;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), m_nPort));
cout << "Waiting for connection..." << endl;
while(true)
{
try
{
boost::shared_ptr<tcp::socket> socket =
boost::make_shared<tcp::socket>(boost::ref(io_service));
acceptor.accept(*socket);
cout << "connection accepted." << endl;
boost::thread workerThread2(request_response_loop, socket);
}
catch(exception &e)
{
cerr << e.what() << endl;
}
}
}
Next time show the entire error message.
Your problem is that your thread procedure wants a reference to the socket, but the socket is a local variable. The acceptor_loop function doesn't wait, so it will destroy the socket as soon as it goes out of scope.
You need to use dynamic or static lifetime, never automatic, for variables passed between threads.