Learning boost, and compiled their daytime server client example. Since I cant use port 13 that is in the example I only changed the port numbers in the server and client example. Server runs fine, but the client doesnt connect it seems, and no error is given.
Input data for the client is "127.0.0.1".
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::endpoint endpoint(tcp::v4(), 8087);
tcp::acceptor acceptor(io_service, endpoint);
for (;;)
{
tcp::iostream stream;
acceptor.accept(*stream.rdbuf());
stream << "test" << make_daytime_string();
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
And the client:
#include <iostream>
#include <string>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
int main(int argc, char* argv[])
{
try
{
if (argc != 2)
{
std::cerr << "Usage: daytime_client <host>" << std::endl;
return 1;
}
tcp::iostream s(argv[1], 8087);
std::string line;
std::getline(s, line);
std::cout << line << std::endl;
}
catch (std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
}
return 0;
}
What worked for me was to change the way I create the endpoint from
tcp::endpoint( tcp::v4(), port );
to
tcp::endpoint( boost::asio::ip::address::from_string("127.0.0.1"), port );
The first method creates an endpoint of 0.0.0.0 which works fine on Mac OS X, but gives the "not valid" message on Windows (XP, building with MSVC 2008).
I wouldn't mind knowing WHY the difference, but at least it works.
A few things would help to debug this for you:
What platform are you running
What compiler are your using, including version
What version of boost are you using
Also, one thing to check is whether the server is binding to 127.0.0.1 or the external interface. Try using the IP address of your external interface instead of 127.0.0.1. Check this in windows using ipconfig and in linux using ifconfig.
Hmm, all works on 1_36 boost version and msvc 2005 compiller.
Check your firewall settings.
The port option takes a string, which may be the name of the service, as "daytime", and then it will look up the corresponding port, or explicitly the port, but it must be a string:
tcp::iostream s(argv[1], "8087");
Related
I know this is probably a really simple problem but ive been trying to get the asio examples to work correctly for over a week now. whenever I run the program, the terminal hangs and dosent print anything and dosent send any info to the client. Im using Ubuntu Linux and a basic compiler command
g++ main.cpp -o main.exe -I include
#define ASIO_STANDALONE;
#include <ctime>
#include <iostream>
#include <string>
#include <asio.hpp>
using asio::ip::tcp;
int main()
{
try
{
asio::io_context io_context;
tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), 1326));
for (;;)
{
std::cout << "hi";
tcp::socket socket(io_context);
acceptor.accept(socket);
std::string message = "e";
asio::error_code ignored_error;
asio::write(socket, asio::buffer(message), ignored_error);
break;
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
any help would be much appreciated
the terminal hangs and dosent print anything and dosent send any info to the client
You need to connect a client first, because the first thing you do is a blocking accept which never completes unless a connection arrives.
I've compiled your program (with minor modification for Boost Asio):
Live On Coliru
//#define ASIO_STANDALONE
#include <boost/asio.hpp>
#include <ctime>
#include <iostream>
#include <string>
namespace asio = boost::asio;
using asio::ip::tcp;
using boost::system::error_code;
int main() {
try {
asio::io_context io_context;
tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), 1326));
for (;;) {
tcp::socket socket(io_context);
acceptor.accept(socket);
std::cout << "hi " << socket.remote_endpoint() << std::endl;
std::string message = "server message works\n";
error_code ignored_error;
asio::write(socket, asio::buffer(message), ignored_error);
break;
}
} catch (std::exception const& e) {
std::cerr << e.what() << std::endl;
}
}
Using netcat to emulate a client:
nc 127.0.0.1 1326 -w 1 <<< "Hello world"
We see:
hi 127.0.0.1:45448
server message works
Or more clearly in separate terminals:
I tried to make a networking TS version of this tutorial:
https://www.boost.org/doc/libs/1_75_0/doc/html/boost_asio/tutorial/tutdaytime2/src.html
First, I compiled and ran the boost version, and it works fine.
Then I wrote this:
#include <ctime>
#include <iostream>
#include <string>
#include <experimental/net>
namespace net = std::experimental::net;
/////////////////////////////////////////////////////////////////////////////
std::string make_daytime_string()
/////////////////////////////////////////////////////////////////////////////
{
time_t now = std::time(0);
const std::string result = std::ctime(&now);
std::cout << "sending: " << result << '\n';
return result;
}
/////////////////////////////////////////////////////////////////////////////
int main()
/////////////////////////////////////////////////////////////////////////////
{
try
{
net::io_context io_context;
net::ip::tcp::acceptor acceptor
(
io_context,
net::ip::tcp::endpoint(net::ip::tcp::v4(), 8013)
);
while (true)
{
net::ip::tcp::socket socket(io_context);
acceptor.accept(io_context);
net::write(socket, net::buffer(make_daytime_string()));
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
I am using the implementation of the networking ts available there:
https://github.com/chriskohlhoff/networking-ts-impl
I am doing this in Ubuntu 20.04 LTS, compiling with gcc.
The server code compiles, and runs. But as soon as a client makes a connection, it fails with this exception:
write: Bad file descriptor
, and the client does not receive anything. My code looks really equivalent to the asio one. Why does it fail?
net::ip::tcp::socket socket(io_context);
acceptor.accept(io_context);
You're discarding the connected socket (and redundantly constructing one from the execution context that you already pass to accept anyways).
Fix it with
auto socket = acceptor.accept(io_context);
I've been unable to connect to Watson's Text-To-Speech service via websockets in C++ using the Boost Beast library
I've got code that successfully interfaces with echo.websocket.org on port 80, but it does not work with Watson's url. I've tried using variants of protocols (http(s), ws(s), and unspecified (which works for echo.websocket.com)) and I've tried both port 80 and 443, just to be sure.
I was able to get successful code running in Javascript, and using Firefox's inbuilt networking tool, I've verified it works over port 443. Using the exact same URL and port number gives me the following: "No such host is known."
Here is the relevant JS code that correctly establishes connection
var completeUrl = "wss://stream.watsonplatform.net/text-to-speech/api/v1/synthesize?access_token=" + accessToken + "&voice=en-US_AllisonVoice";
socket = new WebSocket(completeUrl);
The following C++ code works fine in theory, and works with echo.websocket.org on port 80, but not Watson.
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
namespace websocket = boost::beast::websocket; // from <boost/beast/websocket.hpp>
// Sends a WebSocket message and prints the response
int main(int argc, char** argv)
{
try
{
std::string accessToken = "XXXXX";
auto const text = "The quick brown fox jumps over the lazy dog.";
std::string baseURL = "wss://stream.watsonplatform.net/text-to-speech/api/v1/synthesize";
std::string voiceModel = "en-US_AllisonVoice";
auto const port = "443"; // port 80 for echo.websocket.org
// port 443 for watson
std::string const host = baseURL + "?access_token=" + accessToken + "&voice=" + voiceModel;
//std::string const host = "echo.websocket.org";
boost::asio::io_context ioc;
tcp::resolver resolver{ ioc };
websocket::stream<tcp::socket> ws{ ioc };
auto const results = resolver.resolve(host, port); // Problem line - "resolve: No such host is known"
std::cout << "Host resolved" << std::endl;
boost::asio::connect(ws.next_layer(), results.begin(), results.end());
ws.handshake(host, "/");
std::cout << "Connection established" << std::endl << "------------------------------" << std::endl;
ws.write(boost::asio::buffer(std::string(text)));
std::cout << "Client request: " << text << std::endl;
boost::beast::multi_buffer buffer;
ws.read(buffer);
ws.close(websocket::close_code::normal);
std::cout << "Server response: " << boost::beast::buffers(buffer.data()) << std::endl;
}
catch (std::exception const& e)
{
std::cerr << "Error: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
If the Watson URL was wrong, it shouldn't work in Javascript. If the C++ code was wrong, it shouldn't work with echo.websocket.org. So I have no idea what the issue is.
The baseURL in your code specifies "wss" which means Secure Websockets (SSL). But your stream is delcared as a plain stream. If you want to connect to secure websocket servers, you should base your code on the websocket-client-ssl example instead:
https://github.com/boostorg/beast/blob/d43d9421a40c0251614bc45ea6dcf921a3dbaf37/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp#L64
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.
Above is my code which im using calling from my browser and other client. But it doesnt seem to work. Is there anything wrong? I want to know on which ip im running my server and how this can be used to create a restful webservice.
#include <ctime>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
using namespace std;
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(), 13));
for (;;) {
cout << "listening for socket" << endl;
tcp::socket socket(io_service);
acceptor.accept(socket);
cout << "listening for socket" << endl;
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;
}
}
I'd guess that you are not running the program with sufficient permission to open the privileged (<1024) port 13.
Trying with 1313 works for me (without administrative privileges)