Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Azure VM上Azure web应用程序与windows窗体应用程序之间的通信_C#_Azure_Asp.net Mvc 4_Signalr - Fatal编程技术网

C# Azure VM上Azure web应用程序与windows窗体应用程序之间的通信

C# Azure VM上Azure web应用程序与windows窗体应用程序之间的通信,c#,azure,asp.net-mvc-4,signalr,C#,Azure,Asp.net Mvc 4,Signalr,这是我第一个使用Azure的项目。所以,如果我问的是一个非常基本的问题,请耐心等待 我有一个在Azure服务器上运行的web应用程序。我还有一个windows窗体应用程序,它托管在Azure VM上。根据要求,web应用程序将在需要时与windows窗体应用程序建立连接,向窗体应用程序发送通知,接收响应并切断连接。所以在这里,Web应用程序就像客户端,而Windows窗体应用程序就像服务器 我试着用信号器。已在Azure portal上激活Windows窗体应用程序的端点和端口。我能够建立连接,

这是我第一个使用Azure的项目。所以,如果我问的是一个非常基本的问题,请耐心等待

我有一个在Azure服务器上运行的web应用程序。我还有一个windows窗体应用程序,它托管在Azure VM上。根据要求,web应用程序将在需要时与windows窗体应用程序建立连接,向窗体应用程序发送通知,接收响应并切断连接。所以在这里,Web应用程序就像客户端,而Windows窗体应用程序就像服务器

我试着用信号器。已在Azure portal上激活Windows窗体应用程序的端点和端口。我能够建立连接,但从未从Windows窗体应用程序获得连接确认

我使用的是正确的技术还是有更好的方法?我希望有人能提出一个合适的解决方案

这是我试过的

Windows窗体应用程序中的服务器端代码

  • Nuget安装了Microsoft.AspNet.signal软件包

  • 从Azure门户激活VM端点和端口#12345

  • VM的DNS名称-abc.xyz.net

  • 端点端口号-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)
        { }            
    }
    
    }

    公共类CalcHub:Hub
    {            
    公共异步任务地址编号(整数编号1,整数编号2)
    {
    MessageBox.Show(“添加数字”);
    返回no1+no2;
    }        
    }
    
  • web应用程序中的客户端代码

  • Nuget安装了Microsoft.AspNet.signal.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;
    }
    
    公共类NotificationAppClient
    {
    Microsoft.AspNet.signal.Client.HubConnection connectionFr;
    IHubProxy用户hubproxy;
    public void InitiateServerConnection()
    {
    connectionFr=new Microsoft.AspNet.signar.Client.HubConnection(“http://abc.xyz.net:12345/CalcHub”,useDefaultUrl:false);
    connectionFr.TransportConnectTimeout=新的时间跨度(0,0,60);
    connectionFr.DeadlockErrorTimeout=新的时间跨度(0,0,60);
    userHubProxy=connectionFr.CreateHubProxy(“CalcHub”);
    userHubProxy.On(“addMessage”,参数=>{
    控制台写入线(参数);
    });
    connectionFr.Error+=异步(错误)=>
    {
    等待任务。延迟(新随机()。下一个(0,5)*1000);
    等待连接fr.Start();
    };
    }
    公共异步任务AddNumbers()
    {
    尝试
    {
    int结果=-1;
    connectionFr.Start().Wait(30000);
    if(connectionFr.State==ConnectionState.Connecting)
    {
    连接fr.Stop();
    }
    其他的
    {
    int num1=2;
    int num2=3;
    结果=等待userHubProxy.Invoke(“AddNumbers”,num1,num2);
    }
    连接fr.Stop();
    返回结果;
    }
    捕获(例外情况除外)
    { }
    返回0;
    }
    
    }

  • 实际上,没有必要经常连接和断开连接。持久连接也可以工作


    感谢您的回复

    ,因此即使代码很凌乱,也能正常工作。通常这是一个防火墙问题,所以我会绝对确保两个服务之间的端口一直处于打开状态。检查Windows防火墙和Azure网络安全组中的防火墙,以确保端口已打开。我建议再次检查“有效的安全规则”。如果存在多个安全组,则很容易在一个组中打开端口,而忽略另一个

    为了排除DNS问题,您可以更改
    const string ServerURI=”http://abc.xyz.net:12345";到“http://*:12345”,然后尝试通过公共IP连接

    最后,如果catch块实际上是空的,而不仅仅是缩短代码,那么可以删除它们,或者在其中添加允许您看到错误的内容。正如现在一样,任何错误都只是被吞没,而不知道它们是否正在发生。我没有得到任何运行你的代码,但这将是很好的,以确保


    就通信方法而言,如果您要坚持使用Signal,我会将打开客户端上的连接移动到
    InitiateServerConnection()
    中,并在客户端处于活动状态时保持打开状态。这是hoq信号器的设计工作,而不是每次打开和关闭连接。如果您的最终目标是将信息从表单应用程序实时推送到web应用程序,而不是web应用程序拉取数据,那么这很好。对于你目前正在做的事情来说,这并不理想

    对于这种用例,我强烈建议使用WebAPI而不是signar。如果您打算添加更多的端点,那么与WebApi相比,使用SignalR将变得越来越困难。如果您需要将数据推送到web客户机,但也希望能够按需请求信息,则完全可以并行使用这两种方法

    服务器上的
    Startup
    方法略有变化,因为正在设置的是Microsoft.AspNet.WebApi,而不是Signal:

    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);
        }
    }
    
    您创建的不是集线器,而是控制器

    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;
        }
    }
    
    在客户端,事情变得简单多了,因为您不再需要管理通常是持久连接的东西<代码>InitiateServerConnection()
    可以完全消失
    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;
    }
    
    公共静态异步任务AddNumbers(int num1,int num2)
    {
    尝试
    {
    使用(var client=new HttpClient())
    {
    返回Int32.Parse(wait client.GetStringAsync($“http://:12345/api/add?num1={num1}&num2={num2}”);
    }
    }
    捕获(例外e)
    {
    //做一些例外的事情
    }
    返回0;
    }
    

    如果最终无法解决问题,请告诉我,我们可以继续进行故障排除。

    因此,即使代码很混乱,代码也可以正常工作。通常这是一个防火墙问题,所以我会绝对确保两个服务之间的端口一直处于打开状态。检查Windows防火墙和Azure网络安全组中的防火墙,以确保端口已打开。我推荐
    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;
        }
    }
    
    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;
    }