试图改进我的TCP端口重试ping

时间:2015-12-07 07:29:39

标签: c# winforms tcp

我正在尝试使用我的cefSharp winform项目加载两个网页。第一页肯定会显示出来,因为它是一个本地的html页面。第二页需要ping,因为它是一个服务器网站。我需要先检查服务器IP和端口是否可以先连接,然后重定向到该页面。以下是我的编码:

    public Form1()
    {
        Console.WriteLine("-------Initialization------");
        InitializeComponent();

        this.StartPosition = FormStartPosition.Manual;
        this.Location = new Point(0, 0);

        BrowserSettings browserSettings = new BrowserSettings();
        Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory + "html\\index.html");
        browser = new CefSharp.WinForms.ChromiumWebBrowser(AppDomain.CurrentDomain.BaseDirectory + "html\\index.html") 
        {// First page.
            Dock = DockStyle.Fill,
        };
        this.Controls.Add(browser);
        browser.BrowserSettings.WebSecurity = CefState.Disabled;
        browser.BrowserSettings.FileAccessFromFileUrls = CefState.Enabled;
        browser.BrowserSettings.UniversalAccessFromFileUrls = CefState.Enabled;

        while (true)
        {
            pSvr = PingServer(ioIP, int.Parse(ioPort));
            if (pSvr == true)
            {
                label3.Text = "Connected to server. Please wait...";
                tmr.Interval = 15000; 
                tmr.Tick += timerHandler;
                tmr.Start();
                break;
            }
            Thread.Sleep(5000);
        }
  }

    public bool PingServer(string _HostIP, int _PortNumber)
    {
        try
        {
            TcpClient client = new TcpClient(_HostIP, _PortNumber);
            Console.WriteLine("Server successfully connected...");
            return true;
        }
        catch
        {
            Console.WriteLine("Error pinging server...");
            return false;
        }
    }

    private void timerHandler(object sender, EventArgs e)
    {
        tmr.Stop();
            browser.Load("http://" + ioIP + ":" + ioPort + "/page2/?1"); // second page
    }

我使用while循环并执行thread.sleep 5秒钟,以便在失败时重试连接到服务器。

从逻辑上讲,无论我是否可以连接到第二页,我都希望首先显示第一页,然后在后台重试连接到第二页。但是当我运行我的代码时,当它无法连接到服务器时,第一页就不会出现了。好像它进入while循环并继续重试连接到第二页而忘记显示第一页。这是while循环问题吗?是否始终显示“错误ping服务器...”阻止显示第一页?那么你们认为它是最适合我重试连接服务器的方式?

1 个答案:

答案 0 :(得分:0)

  

你们认为它是最适合我重试连接服务器的方式吗?

恕我直言,你不应该打扰“ping”。真正重要的是你是否可以加载页面。服务器完全无法访问只是其可能失败的众多可能原因之一,即使您成功“ping”服务器,您仍然可能在“ping”之后但在加载页面之前丢失连接,或者看到失败其他一些原因。

不要试图检测服务器。只需加载页面并处理异常(如果发生)。


至于更大的问题,第一页没有出现,这是因为你在构造函数中做得太多了。构造函数在UI线程中执行,该线程负责对程序的可视外观进行所有更新。在从构造函数返回之前,该线程无法执行任何操作。因此,即使您已加载页面,控件也无法在屏幕上反映出来;你的构造函数正在捆绑线程。

基本解决方案是“不要那样做”。有很多方法可以避免这样做,但在这种情况下我觉得,因为你不应该首先“ping”服务器,你可以通过摆脱它来解决你的问题:

public Form1()
{
    Console.WriteLine("-------Initialization------");
    InitializeComponent();

    this.StartPosition = FormStartPosition.Manual;
    this.Location = new Point(0, 0);

    BrowserSettings browserSettings = new BrowserSettings();
    Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory + "html\\index.html");
    browser = new CefSharp.WinForms.ChromiumWebBrowser(AppDomain.CurrentDomain.BaseDirectory + "html\\index.html") 
    {// First page.
        Dock = DockStyle.Fill,
    };
    this.Controls.Add(browser);
    browser.BrowserSettings.WebSecurity = CefState.Disabled;
    browser.BrowserSettings.FileAccessFromFileUrls = CefState.Enabled;
    browser.BrowserSettings.UniversalAccessFromFileUrls = CefState.Enabled;

    tmr.Interval = 15000; 
    tmr.Tick += timerHandler;
    tmr.Start();
}

这将立即加载第一页,等待15秒,然后尝试加载第二页。如果服务器在那里,它将显示。如果没有,你将得到一个未处理的例外;最好在try / catch放置,并向用户提供一些有用的信息和选项(例如“无法连接,重试?”)。


如果你觉得你真的必须显示"Connected to server. Please wait..."消息,即执行ping,那么你应该异步地这样做。例如:

protected override async void OnLoad(EventArgs e)
{
    while (true)
    {
        pSvr = await PingServer(ioIP, int.Parse(ioPort));
        if (pSvr == true)
        {
            label3.Text = "Connected to server. Please wait...";
            tmr.Interval = 15000; 
            tmr.Tick += timerHandler;
            tmr.Start();
            break;
        }
        await Task.Delay(5000);
    }
}

async Task<bool> PingServer(string _HostIP, int _PortNumber)
{
    try
    {
        TcpClient client = new TcpClient();
        await client.ConnectAsync(_HostIP, _PortNumber);
        Console.WriteLine("Server successfully connected...");
        return true;
    }
    catch
    {
        Console.WriteLine("Error pinging server...");
        return false;
    }
}

以上内容将完全替换构造函数中的循环(包括启动计时器...注意这意味着第二页将在加载第一页后不加载15秒,而是在成功检测到服务器后15秒加载)。