简体   繁体   English

Azure Web应用程序与Azure VM上Windows窗体应用程序之间的通信

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

This is my first project using Azure. 这是我使用Azure的第一个项目。 So if I am asking very basic question, please be patient with me. 因此,如果我要问一个非常基本的问题,请耐心等待。

I have a web application which runs on Azure server. 我有一个在Azure服务器上运行的Web应用程序。 I also have a windows form app which is hosted on Azure VM. 我也有一个Windows窗体应用程序,该应用程序托管在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. 根据要求,Web应用程序将在需要时与Windows窗体应用程序建立连接,将向该窗体应用程序发送通知,从中接收响应并切断连接。 So here Web app is like a client and a Windows form app is like a server. 因此,这里的Web应用程序就像一个客户端,而Windows窗体应用程序就像一个服务器。

I tried using SignalR. 我尝试使用SignalR。 Activated the end point and a port for the Windows form app on Azure portal. 在Azure门户上激活了Windows窗体应用程序的端点和端口。 I was able to establish the connection but never getting the confirmation of that connection back from the Windows Form app. 我能够建立连接,但从未从Windows Form应用程序获得该连接的确认。

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 Windows窗体应用程序中的服务器端代码

  1. Installed the Microsoft.AspNet.SignalR package by Nuget 由Nuget安装了Microsoft.AspNet.SignalR程序包

  2. Activated the VM end point and port #12345 from Azure portal 从Azure门户激活了VM端点和端口#12345

  3. DNS name of VM - abc.xyz.net VM的DNS名称-abc.xyz.net

  4. Endpoint port number - 12345 端点端口号-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 Web应用程序中的客户端代码

  1. Installed the Microsoft.AspNet.SignalR.Client by Nuget 由Nuget安装了Microsoft.AspNet.SignalR.Client

     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. 检查Windows防火墙和Azure网络安全组中的防火墙,以确保端口处于打开状态。 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"; 为了排除DNS问题,您可以更改const string ServerURI = "http://abc.xyz.net:12345"; to `"http://*:12345" and try connecting over the public IP. 到““ http:// *:12345”,然后尝试通过公共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. 最后,如果catch块实际上是空的,而不是仅仅缩短代码,要么将其删除,要么在其中添加一些使您看到错误的内容。 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. 就通信方法而言,如果您坚持使用SignalR,我将在客户端处于活动状态时将打开客户端上的连接移至InitiateServerConnection()并保持打开状态。 This is hoq SignalR is designed to work as opposed to opening and closing the connection each time. 这是SignalR设计的目的,而不是每次都打开和关闭连接。 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. 如果您的最终目标是将信息从表单应用程序实时推送到Web应用程序,而不是Web应用程序提取数据,那么这很好。 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. 对于这种用例,我强烈建议您查看WebAPI而不是SignalR。 If you are going to add more endpoints SignalR is going to get increasingly difficult to work with in comparison to WebApi. 如果要添加更多的端点,与WebApi相比,SignalR的使用将变得越来越困难。 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. 如果您需要将数据推送到Web客户端,但又希望能够按需请求信息,则绝对可以并行使用。

The Startup method on the server changes just a bit as Microsoft.AspNet.WebApi is what is being setup instead of SignalR: 由于正在设置Microsoft.AspNet.WebApi而不是SignalR,因此服务器上的Startup方法仅稍作更改:

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. InitiateServerConnection()可以完全消失。 AddNumbers() becomes a simple http call: AddNumbers()变成一个简单的http调用:

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. 如果仍不能解决问题,请通知我,我们可以继续进行故障排除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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