I'm trying to simulate a ping operation to find out if a remote host is reachable. I could not find any conclusive code samples to do this for WP7 so I figured I'd try out the following.
What I'm looking for is confirmation of whether this is the appropriate way to do this.
Socket socket =
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.RemoteEndPoint = new DnsEndPoint (someIP, 80); // use HTTP port 80
args.Completed += (obj, eva) =>
{
if (eva.SocketError != SocketError.Success)
{
//raise an error or set a view model property indicating error
}
socket.Close();
};
socket.ConnectAsync(args);
Unless things have changed in Mango, you can only really reach other hosts with HTTP or HTTPS anyway - so "reachable" really means "is listening for web requests on a known URL"... so the simplest approach would be to make some harmless web request to the relevant server. WebClient is probably the simplest way of doing that, although in my experience it does more work on the UI thread than you'd really expect, so I've ended up using the lower-level HttpWebRequest. For a single ping-like request, you may be okay to use WebClient.
Related
Under load in production we receive "RabbitMQ.Client.Exceptions.ConnectFailureException" connection failed and "MassTransit.RequestTimeoutException" timeout waiting for response. The consumer does receive the message and send it back. It's like the web app isn't listening, or unable to accept the connection.
We're running an ASP.NET web application ( not MVC ) on .NET Framework 4.6.2 on Windows Server 2019 on IIS. We're using MassTransit 7.0.4. In production, under load, we can get some exceptions dealing with sockets on RabbitMQ or timeouts from masstransit. It's difficult to reproduce them in Dev. RabbitMQ is in a mirror, it seems to happen once we turn on a high-load service that bumps from 140 message/sec to 250 message/sec.
I have a few questions about the code architecture, and then if anyone else is running into these kinds of timeout issues.
Questions:
Should I have static scope for the IBusControl? IE, should it be static inside Global asax? And does it matter at all if it's a singleton underneath?
Should I create a new IBusControl and start it per request ( maybe stick it in Application BeginRequest ). Would that make a difference?
Would adding another worker process affect the total number of open connections I'm able to make -- If this is a resource issue ( exhausting threads, connections or some resource ).
Exceptions:
MassTransit.RequestTimeoutException
Timeout Waiting for response
Stacktrace:
System.Runtime.ExceptionServices.ExceptionDispathInfo.Throw
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
MassTransit.Clients.ResponseHandlerConnectionHandle`1+<GetTask>d_11.MoveNext
System.Threading.ExecutionContext.RunInternal
RabbitMQ.Client.Exceptions.ConnectFailureException
Connection failed
Statcktrace:
RabbitMQ.Client.Impl.SocketFrameHandler.ConnectOrFail
RabbitMQ.Client.Impl.SocketFrameHandler.ConnectUsingAddressFamily
RabbitMQ.Client.Impl.SocketFrameHandler..ctor
RabbitMQ.Client.ConnectionFactory.CreateFrameHandler
RabbitMQ.Client.EndPointResolverExtensions.SelectOne
RabbitMQ.Client.ConnectionFactory.CreateConnection
How Our Code Works ( overview )
Static IBusControl that is instantiated the first time someone tries to produce a message. The whole connection and send code is a little large to put in here ( connection factory and other metric classes, but below are the interesting parts ).
Static IBusControl B;
B = Bus.Factory.CreateUsingRabbitMq(x =>
{
hostAddress = host.HostAddress;
x.Host(new Uri(host.HostAddress), h =>
{
h.Username(host.UserName);
h.Password(host.Password);
});
x.Durable = false;
x.SetQueueArgument("x-message-ttl", 600000);
});
B.Start(new TimeSpan(0, 0, 10));
// Then send the Actual Messages
// Generic with TRequest and TResponse : class BaseMessage
// Pulling the code out of a few different classes
string serviceAddressString = string.Format("{0}/{1}?durable={2}", HostAddress, ChkMassTransit.QueueName(typeof(TRequest), typeof(TResponse)), false ? "true" : "false");
Uri serviceAddress = new Uri(serviceAddressString);
RequestTimeout rt = RequestTimeout.After(0, 0, 0, 0, timeout.Value);
IRequestClient<TRequest> reqClient = B.CreateRequestClient<TRequest>(serviceAddress, rt);
var v = reqClient.GetResponse<TResponse>(request, sendInfo.CT, sendInfo.RT);
if ( v.Wait(timeoutMS) ) { /*do some stuff*/ }
First, I find your lack of async disturbing. Using Wait or anything like it on TPL-based code is a recipe for death and destruction, pain and suffering, dogs and cats living together, etc.
Yes, you should have a single bus instance that is started when the application starts. Since you're doing request/response, set AutoStart = true on the bus configurator to make sure it's all warmed up and ready.
Never, no, one bus only!
Each bus instance only has a single connection, so you shouldn't see any resource issues related to capacity on RabbitMQ.
MassTransit 7.0.4 is really old, you might consider the easy upgrade 7.3.1 and see if that improves things for you. It's the last version of the v7 codebase available.
I'm trying to make a web server in Rust for a simple browser game. I want the server to be able to deliver pages through HTTPS, but also be able to communicate through WebSockets. I'm planning to put this server on Heroku, but since they only allow one port per application I have to make the WebSocket server operate on the same port as the other HTTPS code.
It seems like this is possible with crates like rust-websocket, but that crate uses an outdated version of hyper and seems to be no longer maintained. The crate tokio_tungstenite is much more up to date.
The problem is that both hyper and tungstenite have their own implementation of the HTTP protocol that WebSockets operate over with no way to convert between the two. This means that once an HTTPS request has been parsed by either hyper or tungstenite there is no way to continue the processing by the other part, so you can't really try to connect the WebSocket and match on an error in tungstenite and process it by hyper, nor can you parse the request by hyper and check if it's a WebSocket request and send it over to tungstenite. Is there any way to resolve this problem?
I think it should be possible to do that, the tungstenite and tokio-tungstenite allow you to specify custom headers (there are helpers functions for that, prefixed with hdr), so depending on the hyper version you use, if you can convert a request to some form, when the headers can be extracted, you can pass them to tungstenite.
You might also want to try warp crate, it's built on top of hyper and it uses tungstenite under the hood for the websocket support, so if you want to write your own version of warp, you can take a look at the source code (the source code may contain hints on how to use hyper and tungstenite together).
You can do it, but it's quite fiddly. You'll have to use tokio-tungstenite, do the handshake yourself (check header, set response headers) and spawn a new future on the runtime that will handle the websockets connection. The new future can be created by calling on_upgrade() on the request body with the latest version of hyper, and the connection can then be passed to tokio_tungstenite::WebSocketStream::from_raw_socket to turn it into a websockets connection.
Example handler (note that this doesn't fully check the request headers and assumes we want an upgrade):
fn websocket(req: Request<Body>) -> Result<Response<Body>, &'static str> {
// TODO check other header
let key = match req.headers().typed_get::<headers::SecWebsocketKey>() {
Some(key) => key,
None => return Err("failed to read ws key from headers"),
};
let websocket_future = req
.into_body()
.on_upgrade()
.map_err(|err| eprintln!("Error on upgrade: {}", err))
.and_then(|upgraded| {
let ws_stream = tokio_tungstenite::WebSocketStream::from_raw_socket(
upgraded,
tokio_tungstenite::tungstenite::protocol::Role::Server,
None,
);
let (sink, stream) = ws_stream.split();
sink.send_all(stream)
.map(|_| ())
.map_err(|err| error!("{}", err))
});
hyper::rt::spawn(websocket_future);
let mut upgrade_rsp = Response::builder()
.status(StatusCode::SWITCHING_PROTOCOLS)
.body(Body::empty())
.unwrap();
upgrade_rsp
.headers_mut()
.typed_insert(headers::Upgrade::websocket());
upgrade_rsp
.headers_mut()
.typed_insert(headers::Connection::upgrade());
upgrade_rsp
.headers_mut()
.typed_insert(headers::SecWebsocketAccept::from(key));
Ok(upgrade_rsp)
}
Couple of days ago I ran into some kind of a problem that I can't seem to solve. So that's why I'm posting it on StackOverflow.
I'm running a .NET CORE website that can run a task in the background. Such a task has 3 events (OnCompleted, OnStarted, TaskProgress). What I need is that if any of these events fire, he will send data to the connected clients. For simplicity, I want to return the "event fired" string.
What I have done for the moment is the following:
added app.UseWebSockets() to my startup.cs file
added a new function to the pipeline to catch the websocket calls
app.Use(async (context, next) =>
{
if (context.Request.Path == "/socket")
{
if (context.WebSockets.IsWebSocketRequest)
{
var webSocket = await context.WebSockets.AcceptWebSocketAsync();
//HERE IS MY PROBLEM
}
else
{
context.Response.StatusCode = 400;
}
}
else
{
await next();
}
});
I created a SocketListener class that receives all 3 events when fired.
private void _taskManager_TaskExecuting(object sender, GenericEventArgs<IScheduledTaskWorker> e)
{
SendData();
}
private void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e)
{
SendData();
}
private void Argument_TaskProgress(object sender, GenericEventArgs<double> e)
{
SendData();
}
So what I would need now is that in the pipeline function (//HERE IS MY PROBLEM line) I somehow wait for unlimited time for any of the events to fire. If they fire, the SocketListener class needs to be aware of the connections and send data back over the WebSocket connection.
The `SendData()' function will need to check for open connections and send the "event fired" string to all of them.
The connection also needs to be closed when navigating away from the page. I think I can manage that with some angular NavigationStart event and then call the socket api with a close message.
I searched on the internet for a good solution but most of the blogpost/tutorials/... are talking about 2-way communication (chat programs,...)
Anyone got an idea how I could fix this problem? If more information is needed I let me know.
Thanks in advance!
Helo Reggi,
I've open sourced an WebSocket application that I built in .NET Core.
I've built it to process generic messages, not only focused on chats.
My idea is use two way communication within the client (WebPage) and the websocket to perform any kind of task.
WebSocket communication works slightly different from what you say on you question, but the code I've written is going to be a good guide.
What you want to do with SendData is going to be like the method 'NotifyAllConnectedSockets' on the controller NotificationController that I've created.
Please take a look to see if it suits to what you want.
BackEnd - https://github.com/asiilva/WSMessageHandler
Front-end - https://github.com/asiilva/ws-message-handler-front
Note: It is a work in progres, either front and back-end.
Feel free to ask any question
Best Regards
I have started to learn web sockets. It is must learn technology in today's time.
But i am curious to learn more about it. My basic question is How many WebSocket connection can be created on Client Side.
My Typically Application is html UI based and on the server i have rest based services. I need to track whether
Session timeout has happed or not
Whether Connection to the server is lost or not ? A kind of pooling program to check with connections is alive or not.
So I am creating 2 websocket objects on client and different url for them.
I hope i have implemented it correctly ?
Basically Browser closes the old websocket connection once you opened to new connection to SAME URL(ws://127.0.0.1:8080/WebSocket-context-root/getResource). You can keep small hack like "ws://127.0.0.1:8080/WebSocket-context-root/getResource/"+k. where k is any number/any random string. On server side just ignore the path variable k.
In this way you can open many number of connection at same time. Browser restriction of max-number-connection per domain is not applying here (Tested on Firefox). I tried max 25 parallel connections.
You can use websocket.readyState to check the status of the web socket connection.
onclose Event of the Web socket have reason code for closed connection.
User below code to test number of active connections.
var x=0
var intervalID = setInterval(function () {
websocket = new WebSocket("ws://127.0.0.1:8080/WebSocketApi/web/chat/"+x);
websocket.onopen = function (evt) {
console.log('open')
}
websocket.onmessage = function (evt) {
console.log('msg');
}
websocket.onclose= function (evt) {
console.log('closed');
}
if (++x === 15) {
window.clearInterval(intervalID);
}
}, 1);
I`m using zero mq 3.2.0 C++ libary. I use zmq_connect to connect a port before zmq_bild. But this function return success. How can I know connect fail? My code is:
void *ctx = zmq_ctx_new(1);
void *skt = zmq_socket(ctx, ZMQ_SUB);
int ret = zmq_connect(skt, "tcp://192.168.9.97:5561"); // 192.168.9.97:5561 is not binded
// zmq_connect return zero
This is actually a feature of zeromq, connection status and so on is abstracted away from you. There is no exposed information you can check to see if you're connected or not AFAIK. This means that you can connect even if the server is temporarily down, and zeromq will handle everything when the server comes available later. This can be both a blessing and a curse.
What most people end up doing if they need to know connection status is to implement some sort of heartbeat. REQ/REP ping/pong for example.
Have a look at the lazy pirate pattern for an example of how to ensure reliability from a client perspective.