简体   繁体   中英

Communication between an Azure web application and a windows form app on Azure VM

This is my first project using Azure. So if I am asking very basic question, please be patient with me.

I have a web application which runs on Azure server. I also have a windows form app which is hosted on Azure VM. According to the requirement, a web app will establish a connection with the windows form app whenever it is required, will send a notification to the form app, receive a response from it and will cut off the connection. So here Web app is like a client and a Windows form app is like a server.

I tried using SignalR. Activated the end point and a port for the Windows form app on Azure portal. I was able to establish the connection but never getting the confirmation of that connection back from the Windows Form app.

Am I using the proper technique or there is a better way to do this? I hope someone will suggest a proper solution.

Here is what I tried

Server side code in Windows form app

  1. Installed the Microsoft.AspNet.SignalR package by Nuget

  2. Activated the VM end point and port #12345 from Azure portal

  3. DNS name of VM - abc.xyz.net

  4. Endpoint port number - 12345

     public partial class FormsServer : Form { private IDisposable SignalR { get; set; } const string ServerURI = "http://abc.xyz.net:12345"; private void btnStart_Click(object sender, EventArgs e) { btnStart.Enabled = false; Task.Run(() => StartServer()); } private void StartServer() { try { SignalR = WebApp.Start<Startup>(ServerURI); } catch (TargetInvocationException) { } } 

    }

     class Startup { public void Configuration(IAppBuilder app) { app.UseCors(CorsOptions.AllowAll); app.MapSignalR("/CalcHub", new HubConfiguration()); } 

    }

     public class CalcHub : Hub { public async Task<int> AddNumbers(int no1, int no2) { MessageBox.Show("Add Numbers"); return no1 + no2; } } 

Client side code in web application

  1. Installed the Microsoft.AspNet.SignalR.Client by Nuget

     public class NotificationAppClient { Microsoft.AspNet.SignalR.Client.HubConnection connectionFr; IHubProxy userHubProxy; public void InitiateServerConnection() { connectionFr = new Microsoft.AspNet.SignalR.Client.HubConnection("http:// abc.xyz.net:12345/CalcHub", useDefaultUrl: false); connectionFr.TransportConnectTimeout = new TimeSpan(0, 0, 60); connectionFr.DeadlockErrorTimeout = new TimeSpan(0, 0, 60); userHubProxy = connectionFr.CreateHubProxy("CalcHub"); userHubProxy.On<string>("addMessage", param => { Console.WriteLine(param); }); connectionFr.Error += async (error) => { await Task.Delay(new Random().Next(0, 5) * 1000); await connectionFr.Start(); }; } public async Task<int> AddNumbers() { try { int result = -1; connectionFr.Start().Wait(30000); if (connectionFr.State == ConnectionState.Connecting) { connectionFr.Stop(); } else { int num1 = 2; int num2 = 3; result = await userHubProxy.Invoke<int>("AddNumbers", num1, num2); } connectionFr.Stop(); return result; } catch (Exception ex) { } return 0; } 

    }

There is actually no need to connect and disconnect constantly. The persistent connection will work as well.

Thanks for the reply

So the code works even if it is messy. Usually this is a firewall issue so I would make absolutely sure the port is open all the way between the two services. Check both the Windows firewall and the one in the Azure Network Security Group to make sure that the port is open. I recommend double checking the "Effective Security Rules". If there are multiple security groups in play it is easy to open the port in one group but forget the other. 在此处输入图片说明

In order to rule out a DNS issue, you can change const string ServerURI = "http://abc.xyz.net:12345"; to `"http://*:12345" and try connecting over the public IP.

Finally if the catch blocks are actually empty as opposed to just shortening the code either remove them or add something in them that allows you to see errors. As is any errors are just being swallowed with no idea if they are happening. I didn't get any running your code, but it would be good to be sure.


As far as the method of communication goes, if you are going to stick with SignalR I would move opening the connection on the client into the InitiateServerConnection() and leave it open as long as the client is active. This is hoq SignalR is designed to work as opposed to opening and closing the connection each time. If your end goal is to push information in real time from your forms app to the web app as opposed to the web app pulling the data this is fine. For what you are currently doing this is not ideal.

For this sort of use case, I would strongly suggest looking at WebAPI instead of SignalR. If you are going to add more endpoints SignalR is going to get increasingly difficult to work with in comparison to WebApi. You can absolutely use both in parallel if you need to push data to the web client but also want to be able to request information on demand.

The Startup method on the server changes just a bit as Microsoft.AspNet.WebApi is what is being setup instead of SignalR:

class Startup
{
    public void Configuration(IAppBuilder app)
    {

        HttpConfiguration config = new HttpConfiguration();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        app.UseCors(CorsOptions.AllowAll);
        app.UseWebApi(config);
    }
}

Instead of a Hub you create a controller.

public class AddController : ApiController
{

    // GET api/add?num1=1&num2=2
    public HttpResponseMessage Get(int num1, int num2)
    {
        var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
        response.Content = new StringContent((num1 + num2).ToString());

        return response;
    }
}

The client side is where things get a lot simpler as you no longer need to manage what is usually a persistent connection. InitiateServerConnection() can go away completely. AddNumbers() becomes a simple http call:

public static async Task<int> AddNumbers(int num1, int num2)
{
    try
    {
        using(var client = new HttpClient())
        {
            return Int32.Parse(await client.GetStringAsync($"http://<sitename>:12345/api/add?num1={num1}&num2={num2}"));
        }
    }
    catch (Exception e)
    {
        //Do something with the exception
    }

    return 0;
}

If that doesn't end up resolving the issue let me know and we can continue to troubleshoot.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM