Want to create one back-end for location sharing between clients and back-end should be in .net-core and MS-SQL.
Simple approach is user1 send x and y co-ordinates and save to db every 2 second and user2 call the get api and get the x and y co-ordinates in every 2 second.
Issue - If 1 million user register then 1 million request per 2 sec will hit. Not good for servers and MS-SQL
Question - Is it possible to create web socket for every user which send their location and send the data to that socket in every 2 sec and when other user who want to see the location, merge that user with socket.
or any other approach???
You can use memory based database (Redis for example) to store the data (save and answer).
Web socket as transport, but even using web sockets you need to store the data somethere. To store in the application - not a good idea.
Maybe you can use SignalR - receive data from one client and send it to all connected clients. But there will be some difficulties with many connections.
You could use Asp.net SignalR, it can send messages to all connected clients simultaneously. For example, a chat room. Or, send messages to specific clients or groups of clients.
The SignalR Hubs API provides the following method to send messages to clients:
SendMessage sends a message to all connected clients, using Clients.All.
SendMessageToCaller sends a message back to the caller, using Clients.Caller.
SendMessageToGroups sends a message to all clients in the SignalR Users group.
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
public Task SendMessageToCaller(string user, string message)
{
return Clients.Caller.SendAsync("ReceiveMessage", user, message);
}
public Task SendMessageToGroup(string user, string message)
{
return Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
}
More details information about using it, check the following links:
Tutorial: Get started with ASP.NET Core SignalR
How can I make one to one chat system in Asp.Net.Core Mvc Signalr?.
Mapping SignalR Users to Connections
Related
I'm using a .NET web app as a buffer between an IoT device and IoT Hub. The IoT device sends data to the web app which then routes that data to Azure IoT Hub. I'm using the Device Client to do this. It worked fine until the number of requests started growing as we went into production.
Here is the bit of code that sends data to IoT Hub.
public async Task SendDataToIoTHub(Message eventMessage, string deviceId, string deviceKey)
{
string connectionString = $"HostName=" + IoTHubHostname + ";DeviceId=" + deviceId + ";SharedAccessKey=" + deviceKey;
using (DeviceClient deviceClient = DeviceClient.CreateFromConnectionString(connectionString))
{
if (deviceClient == null)
{
return;
}
await deviceClient.SendEventAsync(eventMessage);
}
}
I have about 3k-4k requests every minute and the above code gets called for each request. It has really started being unreliable since the request rate hit this amount. There was a ' too many TCP connections' warning for a brief period of time which caused the entire application to start slowing down dramatically.
I'm wondering if this initialization of the device client is correct or if there is a better way to do it.
Thanks!
This could be due to reaching the maximum outbound TCP connections. The limits are:
1,920 connections per B1/S1/P1 instance
3,968 connections per B2/S2/P2 instance
8,064 connections per B3/S3/P3 instance
16,000 connections per I1/I2/I3 instance
Source (This post also shows how to view the number of TCP connections over time)
You're opening a new connection every time you create a new DeviceClient, so with those rates, you will hit some limits. You could scale up your instance, but maybe you should consider keeping a single DeviceClient per device (if you don't have thousands of devices).
There might be a reason for this "web app as a buffer" as you call it, and if you want to continue using it, you might consider using the REST API to send your device events instead. You don't need an AMQP connection if you're only going to send one event.
I'm using SingalR in an application that sends alot messages in a short period of time.
let's say i have client A and client B.
Client A just sends messages and client B just listening to messages.
Client A sends the following messages in the following order: A->B->C->D
What i'm seeing is that Client B sometimes receives the messages in a different order, for example: B->A->C->D
It is important for maintain the same order i sent the messages.
I've looked online and i found people saying i should use async-await on the function on the hub that handles those messages.
public async Task hubMethod(msgObject msg)
{
await Clients.All.message(msg);
}
I'm not sure how that helps since each time i make a call from client A , singalR should create a new instance of the hub.
The only thing it does is wait for the singalR that it finished doing all it can do on the server in order to send the message to the other client and notifies it to client A.
So my question is this - is there a singalR or asp.net mechanism that make sure i receive the messages in the correct order on the other client or do i need to write my own mechanism (server or client) that reorders the messages if they are out of order - and if so, is there a library that already does it?
You need to write your own mechanism. SignalR in client B has no way to know in which order the clients messages were sent by client A because there is many things that could delay a specific message arrival, like network delay, the only thing SignalR can guarantee is the order in which the messages arrived.
If you really need to know the original order of the messages you could put a count inside the message and let client B sort them out. However i suggest you try another approach, because guaranteeing the order of delivery is not a easy task.
I am building a c#/wpf project.
It's architecture is this:
A console application which will be on a virtual machine (or my home computer) that will be the server side.
A wpf application that will be the client app.
Now my problem is this - I want the server to be able to send changes to the clients. If for example I have a change for client ABC, I want the server to know how to call a service on the clients computer.
The problem is, that I don't know how the server will call the clients.
A small example in case I didn't explain it well:
The server is on computer 1, and there are two clients, on computers 2 and 3.
Client 2 has a Toyota car and client 3 has a BMW car.
The server on computer 1 wants to tell client 2 that it has a new car, an Avenger.
How do I keep track and call services on the clients?
I thought of saving their ip address (from calling ipconfig from the cmd) in the DB - but isn't that based on the WI-FI/network they are connected to?
Thanks for any help!
You could try implementing SignalR. It is a great library that uses web sockets to push data to clients.
Edit:
SignalR can help you solve your problem by allowing you to set up Hubs on your console app (server) that WPF application (clients) can connect to. When the clients start up you will register them with a specified Hub. When something changes on the server, you can push from the server Hub to the client. The client will receive the information from the server and allow you to handle it as you see fit.
Rough mockup of some code:
namepsace Server{}
public class YourHub : Hub {
public void SomeHubMethod(string userName) {
//clientMethodToCall is a method in the WPF application that
//will be called. Client needs to be registered to hub first.
Clients.User(userName).clientMethodToCall("This is a test.");
//One issue you may face is mapping client connections.
//There are a couple different ways/methodologies to do this.
//Just figure what will work best for you.
}
}
}
namespace Client{
public class HubService{
public IHubProxy CreateHubProxy(){
var hubConnection = new HubConnection("http://serverAddress:serverPort/");
IHubProxy yourHubProxy = hubConnection.CreateHubProxy("YourHub");
return yourHubProxy;
}
}
}
Then in your WPF window:
var hubService = new HubService();
var yourHubProxy = hubService.CreateHubProxy();
yourHubProxy.Start().Wait();
yourHubProxy.On("clientMethodToCall", () => DoSometingWithServerData());
You need to create some kind of subscription model for the clients to the server to handle a Publish-Subscribe channel (see http://www.enterpriseintegrationpatterns.com/patterns/messaging/PublishSubscribeChannel.html). The basic architecture is this:
Client sends a request to the messaging channel to register itself as a subscriber to a certain kind of message/event/etc.
Server sends messages to the channel to be delivered to subscribers to that message.
There are many ways to handle this. You could use some of the Azure services (like Event hub, or Topic) if you don't want to reinvent the wheel here. You could also have your server application track all of these things (updates to IP addresses, updates to subscription interest, making sure that messages don't get sent more than once; taking care of message durability [making sure messages get delivered even if the client is offline when the message gets created]).
In general, whatever solution you choose is plagued with a common problem - clients hide behind firewalls and have dynamic IP addresses. This makes it difficult (I've heard of technologies claiming to overcome this but haven't seen any in action) for a server to push to a client.
In reality, the client talks and the server listens and response. However, you can use this approach to simulate a push by;
1. polling (the client periodically asks for information)
2. long polling (the client asks for information and the server holds onto the request until information arrives or a timeout occurs)
3. sockets (the client requests server connection that is used for bi-directional communication for a period of time).
Knowing those terms, your next choice is to write your own or use a third-party service (azure, amazon, other) to deliver messages for you. I personally like long polling because it is easy to implement. In my application, I have the following setup.
A web API server on Azure with and endpoint that listens for message requests
A simple loop inside the server code that checks the database for new messages every 100ms.
A client that calls the API, handling the response.
As mentioned, there are many ways to do this. In your particular case, one way would be as follows.
Client A calls server API to listen for message
Server holds onto call, waiting for new message entry in database
Client B calls server API to post new message
Server saves message to database
Server instance from step 2 sees new message
Server returns message to Client A.
Also, the message doesn't have to be stored in a database - it just depends on your needs.
Sounds like you want to track users à la https://www.simple-talk.com/dotnet/asp.net/tracking-online-users-with-signalr/ , but in a desktop app in the sense of http://www.codeproject.com/Articles/804770/Implementing-SignalR-in-Desktop-Applications or damienbod.wordpress.com/2013/11/20/signalr-a-complete-wpf-client-using-mvvm/ .
I am relatively new to SignalR, What I have done so far are example chat applications on it to get started.
We have a project that includes multiple databases, it's a machine data collection app. I have created a web control in ASP.NET MVC to view data of multiple machines at one place.
We have multiple users and they can access machines related to their projects. The current solution have a jQuery observer on the mvc page which refreshes the machine controls in a specific time.
I am thinking of making it a Push Notification solution. But as I am a beginner on SignalR I don't know how to approach this.
The goal is to notify the user of changes in data for machines that the user has access to (Not all machines).
Also how can I send messages from a database server to SignalR notifying of changes in the data?
I need some guidance getting started on this.
SignalR Send method allows you to send data to user! It may use push, frame, server events or websocket techniques. You developer don't care about the technique! It depends on server and client handshake.
What you really need is to retrieve data from your databases and then to users, without worries
// Server side:
protected override Task OnConnected(IRequest request,
string connectionId)
{
var db = new allEntities();
var db2 =new allEntities2();
var data1 = db.Tables.Where(e=>e.LastUpdate<=datetime.now.AddDays(-1));
var data2=db2.Tables.Where(e=>e.Something==someRef);
var data=combine(data1,data2);//combine logic goes here
return Connection.Send(connectionId, data.ToList());
}
Say i have a server that listens to a TCP Port (through TcpListener), and i have five different connections to that server (through TcpClient). How would i go about sending information through streams to each one without giving the wrong information to the wrong client.
For Example:
Five clients all connected to the server.
I have to send the message "this is a message" to Client 1, but i dont want to send that message to client 2, 3, 4 and 5. I also want to send the message "this is another message" to client 3 and 5 but not send that message to client 1, 2 and 4.
How exactly do i go about doing this?
The TcpListener class has the methods AcceptSocket and AcceptTcpClient. They return a different Socket (or TcpClient) for every client that connects to your server – you use these objects to send data to the individual clients.
After you accept Socket or call AcceptTcpClient, you can differentiate them using endpoint. If you want to know what to sent to which endpoint, you should differentiate them using their IP and/or port from which the connection is coming. You can refer to this post to see how to do that getting-the-ip-address-of-a-remote-socket-endpoint
EDIT: You can see how to send/receive data for example here