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.
Related
I am trying to understand what would happen with async_read when there is nothing to read.
For example, a client creates a connection to a server, then start async_read(), but that server does not expect to send anything to this client. So what would happen? Should I receive a EOF?
Updata:
I think #user786653 is right. I made a simple example (see following).
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/asio.hpp>
class test{
public:
test(boost::asio::io_service& io_service):_socket(io_service){
}
void handle_connect(){
std::cout<<"entering test::handle_connect"<<std::endl;
char reply[128];
boost::asio::async_read(_socket, boost::asio::buffer(reply, sizeof(reply)),
[](boost::system::error_code ec, std::size_t /*length*/){
std::cout<<"Read result:"<< ec<<" - "<<ec.message()<<std::endl;
});
}
boost::asio::ip::tcp::socket & socket(){
return _socket;
}
private:
boost::asio::ip::tcp::socket _socket;
};
int main() {
try {
boost::asio::io_service io_service;
boost::asio::ip::tcp::socket s(io_service);
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query("127.0.0.1", "8000");
boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
test t(io_service);
t.socket().async_connect(endpoint,boost::bind(&test::handle_connect, &t));
io_service.run();
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << "\n";
}
}
Quoting from the latest (1.68.0) documentation:
This function is used to asynchronously read a certain number of bytes of data from a stream. The function call always returns immediately. The asynchronous operation will continue until one of the following conditions is true:
The supplied buffers are full. That is, the bytes transferred is equal to the sum of the buffer sizes.
An error occurred.
So nothing will happen until the server closes the connection (resulting in an error).
You can test this out for yourself:
#include <iostream>
#include <boost/asio.hpp>
int main() {
try {
boost::asio::io_context io_context;
boost::asio::ip::tcp::socket s(io_context);
boost::asio::ip::tcp::resolver resolver(io_context);
boost::asio::connect(s, resolver.resolve("localhost", "8000"));
char reply[128];
async_read(s, boost::asio::buffer(reply, sizeof(reply)), [](boost::system::error_code ec, std::size_t /*length*/) {
std::cout << "Read result: " << ec << " - " << ec.message() << "\n";
});
io_context.run();
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << "\n";
}
}
Start a server that doesn't respond on localhost port 8000 (or change the code). E.g. something like nc -l 8000 or python -m SimpleHTTPServer. Then run the program and wait. Nothing happens. Now stop the server, on my (Windows) machine this results in:
Read result: system:10054 - An existing connection was forcibly closed by the remote host
This is not a duplicate! (This is not about UDP, it is TCP. This is not C#, Python or whatever, it is C++)
I get the error described in the title if I try to connect through my external IP. However, it works via "localhost" or "127.0.0.1" (I am running client.exe and server.exe on the same machine). This code was copied from an example and I made minor changes.
EDIT: I gave Firewall permission to both executable files. Still, the problem persists.
Server:
#include <ctime>
#include <iostream>
#include <string>
#include <boost/asio.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);
}
int main()
{
try
{
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 62000));
for (;;)
{
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), ignored_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
{
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query("localhost", "62000");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::endpoint endpoint = *endpoint_iterator;
std::cout << endpoint << "\n\n";
tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);
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); // Some other error.
std::cout.write(buf.data(), len);
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
std::cout << "\n\n";
system("pause");
return 0;
}
It turns out my router won't accept connections from the internet (using external IP) if the request comes from my local network.
As long as the request isn't coming from my local network, the client will connect to the server without problems.
If I want to run both client and server on my machine, I must use my internal IP (127.0.0.1 or my internal network IP).
If someone else wants to connect to my server from outside my local network, it will work fine. But machines inside my local network won't be able to access the server using external IP, only internal IP.
I never saw this happen. But at least it doesn't affect the functionality of my program.
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.
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"<