How to create a simple server/client application using boost.asio? - boost

I was going over the examples of boost.asio and I am wondering why there isn't an example of a simple server/client example that prints a string on the server and then returns a response to the client.
I tried to modify the echo server but I can't really figure out what I'm doing at all.
Can anyone find me a template of a client and a template of a server?
I would like to eventually create a server/client application that receives binary data and just returns an acknowledgment back to the client that the data is received.
EDIT:
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred) // from the server
{
if (!error)
{
boost::asio::async_write(socket_,
boost::asio::buffer("ACK", bytes_transferred),
boost::bind(&session::handle_write, this,
boost::asio::placeholders::error));
}
else
{
delete this;
}
}
This returns to the client only 'A'.
Also in data_ I get a lot of weird symbols after the response itself.
Those are my problems.
EDIT 2:
Ok so the main problem is with the client.
size_t reply_length = boost::asio::read(s,
boost::asio::buffer(reply, request_length));
Since it's an echo server the 'ACK' will only appear whenever the request length is more then 3 characters.
How do I overcome this?
I tried changing request_length to 4 but that only makes the client wait and not do anything at all.

Eventually I found out that the problem resides in this bit of code in the server:
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred) // from the server
{
if (!error)
{
boost::asio::async_write(socket_,
boost::asio::buffer("ACK", 4), // replaced bytes_transferred with the length of my message
boost::bind(&session::handle_write, this,
boost::asio::placeholders::error));
}
else
{
delete this;
}
}
And in the client:
size_t reply_length = boost::asio::read(s,
boost::asio::buffer(reply, 4)); // replaced request_length with the length of the custom message.

The echo client/server is the simple example. What areas are you having trouble with? The client should be fairly straightforward since it uses the blocking APIs. The server is slightly more complex since it uses the asynchronous APIs with callbacks. When you boil it down to the core concepts (session, server, io_service) it's fairly easy to understand.

Related

Autohotkey concerning Websocket | Winhttp and stuff question

Trying to get trading information via websocket method. There are many guides and manuals for other languages, I would like to get it via Autohotkey preferably.
Below is the code that I am using when receiving info with Autohotkey.
Get_Price(Target_Site, Target_Coin, Price_Type = "KRW") {
if (Target_Site = "UpBit") {
API_Url := "https://crix-api-endpoint.upbit.com/v1/crix/candles/minutes/10?code=CRIX.UPBIT."
}
Result_URL := API_Url "" Price_Type "-" Target_Coin
Result_Json := Get_WinHttp(Result_URL)
RegExMatch(Result_Json, "tradePrice"`":(.*?)\.", Result) ;If(Target_Coin="BTT") Or (Target_Coin="DOGE") If(Target_Coin="BTT") Or (Target_Coin="DOGE")RegExMatch(Result_Json, "tradePrice"`":(.*?)\,", Result)
Return Result1
}
It seems like the approach above was kinda more explicit and easy compared to Websocket. Only thing I had to was forming right url with my info and sending that url and get the result from the website.
But, when it comes to websocket, I know of the right url, right info to send, but don't know how I can send and .. yeah how.
Url : wss://api.upbit.com/websocket/v1
What to send : '[{"ticket":"test1243563456"},{"type":"trade",{"type":"trade","codes":["KRW-BTC", "KRW-ETH"]}]'
How : I don't know. But I happen to come across some interesting AHK example, I am wishing I can modifying this. Will appreciate if you can have a look and guide me if possible.
#Include, Websocket.Ahk
class Example extends WebSocket
{
OnOpen(Event)
{
InputBox, Data, WebSocket, Enter some text to send through the websocket.
If (ErrorLevel==1)
this.Close()
this.Send(Data)
}
OnMessage(Event)
{
MsgBox, % "Received Data: " Event.data
new Example("wss://echo.websocket.org/")
}
OnClose(Event)
{
MsgBox, Websocket Closed
this.Disconnect()
}
First things first, in AHK v1 you escape quotes by doing a double quote "".
Here "tradePrice"`":(.*?)\." your resulting string has a double quote in it by pretty much sheer luck.
Actually it's supposed to be done like this: "tradePrice"":(.*?)\.".
You'll need to correctly escape quotes in what you're going to do next.
Also, since you have a json response, you might want to parse the json and use it how it's supposed to be used.(See AHK JSON/Jxon)
So about the websocket.
Personally I'd say G33kDude's example(Github) explains it pretty well, but maybe you were thrown off by the object oriented code style choice he's made for it.
It's not that easy to understand if you're not experienced with OOP/OOP AHK I guess.
Here's an example for calling an echo websocket with the data you wanted to send.
#Include WebSocket.ahk
New HelperClass("wss://echo.websocket.org/")
class HelperClass extends WebSocket
{
OnOpen(Event)
{
DataToSend := "[{""ticket"":""test1243563456""},{""type"":""trade"",{""type"":""trade"",""codes"":[""KRW-BTC"", ""KRW-ETH""]}]"
this.Send(DataToSend)
}
OnMessage(event)
{
MsgBox, % "Received a message!:`n" Event.data
this.Close()
}
OnClose(Event)
{
MsgBox, Websocket Closed
this.Disconnect()
}
OnError(Event)
{
MsgBox, Websocket Error
}
__Delete()
{
MsgBox, Exiting
ExitApp
}
}
You have to make this class that extends the WebSocket class due to how it's designed, but it's actually pretty convenient if you know OOP (AHK).
So here's how it works:
New HelperClass("wss://echo.websocket.org/")
You prepare the behind the scenes magic open a websocket connection to the specified websocket
The OnOpen() function runs in your HelperClass once the magic has been prepared
this.Send(DataToSend)
You call the Send function (which if found inside the WebSocket class) and pass in the data you want
You receive a response message (OnMessage() runs in your HelperClass), or maybe you receive an error (OnError() runs in your HelperClass)
The connection closes, so OnClose() runs in your HelperClass.
And you also want to reset the behind the scenes magic by calling Disconnect() function inside the WebSocket class by doing this.Disconnect()
(When I say inside HelperClass or inside WebSocket class, it's actually incorrect because they're kind of the same class, you're just extending WebSocket class with your HelperClass)
So that's about it.
Misc notes:
Download the WebSocket class from G33kDude's GitHub and include the WebSocket.ahk file to your own script with #Include(docs).
G33kDude example script uses #Include ../WebSocket.ahk to include it, because his example script is in a subfolder, so he goes back one folder with .. and then specifies the file to include.
Also note how the quotation marks are correctly escaped in the DataToSend variable.

Xamarin Android try/catch does not work with udp.SendAsync()

I've built a simple app that talks over UDP, to an endpoint at an IP the user specifies. It uses System.Net.Sockets.UdpClient, which works pretty well on Android - I'm able to send and receive packets fairly consistently. With one glaring exception... Exceptions. It seems to completely evade try/catch; my guess is the underlying implementation errors so hard that errors cannot be caught. For example:
UdpClient Udp { get; protected set; }
Udp.Connect("192.168.1.254"); // Any bad IP
try
{
int bytesSent = await udp.SendAsync(bytes, bytes.Length);
}
catch(Exception ex)
{
return null;
}
When testing on an actual Android device, any UDP traffic sent to a bad IP consistently destroys the application.
The behavior gets crazier. For example, if I put the call out on a background thread, with a nested try/catch, like this:
Task.Run(ping).ConfigureAwait(false);
protected async Task ping()
{
try
{
await checkIp();
}
catch(Exception ex)
{
}
}
Then there are some scenarios where I actually can get an Exception - but only in the outer catch! The throw occurs on the SendAsync call inside the inner try, but the inner catch misses it, landing only in the outer catch. The exception is a System.Net.Sockets.SocketException with type ConnectionRefused. Depending on how exactly I step through it, sometimes that gets caught there, sometimes not at all; when it's not at all, the app just implodes.
Is this expected behavior? Is Xamarin UdpClient just not supposed to be used? Bug? Better approach than SendAsync? Other?

C++ CLI / TS3 Client crashes on plugin

Sooo...
I have written a plugin, and the whole plugin works fine.
ONLY PROBLEM:
My TS3 Client crashes.
To give a context:
(Warning: That code is just poorly pasted. On GitHub, it crashes at line 270 and 285)
// Helper Function
String^ getChannelName(uint64 serverConnectionHandlerID, uint64 channelID) {
char* tmp;
if (ts3Functions.getChannelVariableAsString(serverConnectionHandlerID, channelID, CHANNEL_NAME, &tmp) == ERROR_ok) {
return marshal_as<String^>(tmp);
}
else
{
return "ERROR_GETTING_CHANNELNAME";
}
}
void assemble_a() {
List<String^>^ clients;
List<String^>^ channel;
// Some middlepart here, but I made sure it works as it should
// And the actual part where it is crashing
if (resChL == ERROR_ok) {
for (int i = 0; channelListPtr[i]; ++i) {
String^ a = getChannelName(schid, channelListPtr[i]);
const char* b = (const char*)(Marshal::StringToHGlobalAnsi(a)).ToPointer();
ts3Functions.logMessage(b, LogLevel_DEBUG, "DEBUG_VC", schid);
if (String::IsNullOrEmpty(a) == false) {
channel->Add(a); // It crashes RIGHT at this point
}
}
}
}
So I am asking on the TS3 forum for a long time, got a lot of answers, and noone could tell me why it actually crashes, and I didn't manage to figure it out on my own either.
It does actually print the channel name [*spacer0]t but as soon as it should append it to the String List, it crashes.
It throws the message The thread has tried to write or read from a virtual address that it does not have the accesspermissions for.
I seriously have no idea what to do, trying to fix it now for over 2 weeks.
For full context: GitHub Sourcecode
Sorry if this question MIGHT be a little out of topic here (Is it? I don't know...) but I don't really know what to do with that problem anymore...
EDIT:
Errormessage from try/catch is:
System.NullReferebceException: The Objectreference was not set to the Objectinstance, occured in tsapi.assembleGrammar()
List<String^>^ channel;
...
channel->Add(a);
channel is null. You need to initialize it with something, probably gcnew List<String^>(). I'm not sure why you're getting an access denied message instead of NullReferenceException.
Other issues
Make sure you're handling all the unmanaged strings properly. For example, does getChannelVariableAsString require a call to explicitly free the buffer? Be absolutely sure to call FreeHGlobal to free the memory that StringToHGlobalAnsi allocated for you.

Returning error from SignalR server method

I am new to SignalR and there is a small detail I can't get my head around.
My SignalR hub include many channels and the clients can join one or many of these channels via a server method:
joinChannel(string channelName)
What I don't understand is what this method should return.
If it were a normal "RPC" method I would return a status (200 - Ok, 404 - Not found, 403 - Forbidden etc) via IHttpActionResult.
How do I indicate success/failure in SignalR?
What determines if the reply gets to .done or .fail in the client?
Update
Currently my method returns a non-zero value in case of error.
int joinChannel(string channelName) {
...
return errorCode;
}
This works but it create unnecessarily complicated code in the client
hubProxy.server.joinChannel('channel1')
.done(function (result) {
if (result != 0) {
// error handling
}
})
.fail(function (error) {
// error handling
});
To confirm that your action was successfully performed, you can have a client method call. So, basically it would look like this:
public void ServerMethod(argumentList)
{
if (/* server code executed successfully */)
Clients.Caller.onSuccess(arguments);
else Clients.Caller.onFailure(arguments);
}
What this piece of code does is to notify the caller of the server method of a success/failure by calling a client method - method defined in JavaScript. You can also have a method executed on All clients, or only on specific users.
Since it is not an RPC mechanism, I think this is the closest thing you can do to simulate a return type in SignalR.
Hope this helps!
Best of luck!
What about
HubException in
Microsoft.AspNetCore.SignalR.
This is available in ASP.NET Core.
This exception is thrown on the server and sent to client. You can also derive from that class to put your own information in it.

Get room/rooms of client [duplicate]

I can get room's clients list with this code in socket.io 0.9.
io.sockets.clients(roomName)
How can I do this in socket.io 1.0?
Consider this rather more complete answer linked in a comment above on the question: https://stackoverflow.com/a/24425207/1449799
The clients in a room can be found at
io.nsps[yourNamespace].adapter.rooms[roomName]
This is an associative array with keys that are socket ids. In our case, we wanted to know the number of clients in a room, so we did Object.keys(io.nsps[yourNamespace].adapter.rooms[roomName]).length
In case you haven't seen/used namespaces (like this guy[me]), you can learn about them here http://socket.io/docs/rooms-and-namespaces/ (importantly: the default namespace is '/')
Updated (esp. for #Zettam):
checkout this repo to see this working: https://github.com/thegreatmichael/socket-io-clients
Using #ryan_Hdot link, I made a small temporary function in my code, which avoids maintaining a patch. Here it is :
function getClient(roomId) {
var res = [],
room = io.sockets.adapter.rooms[roomId];
if (room) {
for (var id in room) {
res.push(io.sockets.adapter.nsp.connected[id]);
}
}
return res;
}
If using a namespace :
function getClient (ns, id) {
return io.nsps[ns].adapter.rooms[id]
}
Which I use as a temporary fix for io.sockets.clients(roomId) which becomes findClientsSocketByRoomId(roomId).
EDIT :
Most of the time it is worth considering avoiding using this method if possible.
What I do now is that I usually put a client in it's own room (ie. in a room whose name is it's clientID). I found the code more readable that way, and I don't have to rely on this workaround anymore.
Also, I haven't tested this with a Redis adapter.
If you have to, also see this related question if you are using namespaces.
For those of you using namespaces I made a function too that can handle different namespaces. It's quite the same as the answer of nha.
function get_users_by_room(nsp, room) {
var users = []
for (var id in io.of(nsp).adapter.rooms[room]) {
users.push(io.of(nsp).adapter.nsp.connected[id]);
};
return users;
};
As of at least 1.4.5 nha’s method doesn’t work anymore either, and there is still no public api for getting clients in a room. Here is what works for me.
io.sockets.adapter.rooms[roomId] returns an object that has two properties, sockets, and length. The first is another object that has socketId’s for keys, and boolean’s as the values:
Room {
sockets:
{ '/#vQh0q0gVKgtLGIQGAAAB': true,
'/#p9Z7l6UeYwhBQkdoAAAD': true },
length: 2 }
So my code to get clients looks like this:
var sioRoom = io.sockets.adapter.rooms[roomId];
if( sioRoom ) {
Object.keys(sioRoom.sockets).forEach( function(socketId){
console.log("sioRoom client socket Id: " + socketId );
});
}
You can see this github pull request for discussion on the topic, however, it seems as though that functionality has been stripped from the 1.0 pre release candidate for SocketIO.

Resources