WPF
TCP
networkApp
myVisualStudioStudy

Visual Studio | WPF > TCP接続 > 接続タイムアウト処理 > .NET Framework 4.5以降? > ConnectAsync()使用

動作環境
Windows 8.1 Pro (64bit)
Microsoft Visual Studio 2017 Community
Sublime Text 2

TCPクライアントのソフトを実装中に持った疑問が、相手先がいない場合のタイムアウト処理だった。

実装案

下記を見つけた。
How to set the timeout for a TcpClient?

answered Jun 14 '13 at 23:30
Jonさんによる回答ではBeginConnect()などの処理を使っている。
EndConnect()処理の扱いなど使うことになるため、この方法は使わない。

answered Jun 18 '15 at 13:53
Simon Mourierさんによる.NET 4.5以降では有効との処理を使う。

code

MainWindow.xaml
<Window x:Class="_171207_t1540_tcpConnectFail.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:_171207_t1540_tcpConnectFail"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Name="B_connect" Content="Connect" Height="30"
                Click="B_connect_Click"/>
    </Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
// 以下を追加した
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.ComponentModel;
using System.IO;

namespace _171207_t1540_tcpConnectFail
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void B_connect_Click(object sender, RoutedEventArgs e)
        {
            String ipadr = "192.168.0.79";
            int port = 7000;
            var client = new TcpClient();
            if (client.ConnectAsync(ipadr, port).Wait(1000) == false)
            {
                MessageBox.Show("Connect fail");
            } else {
                MessageBox.Show("Connect OK");
            }

            client.Close();
        }
    }
}

動作環境

.NET Framework バージョン判定(4.5から4.7.1) by @jTakasuRyuji さん
によると、レジストリでどの.NET Frameworkが入っているか確認できるらしい。

自分が使える環境の例として調べた。

  • Windows 7: Releaseキー 見つからず (v4.5未満?)
    • プログラムの機能と追加の「Windowsの機能」ではv3.5のみ
  • Window 8.1: Releaseキー 見つからず
    • OS Integrationにはv4(REG_DWORD)というキーは見つかった。
    • プログラムの機能と追加の「Windowsの機能」ではv3.5とv4.5

結果

Windows 7
qiita.png

Windows 8.1
qiita.png

未消化の点

.NET Framework v3.5しか入っていないWindows 7でも接続失敗を認識した。

Simon Mourierさんの「Starting with .NET 4.5, TcpClient has a cool ConnectAsync method 」という意味が未消化。
ビルド時の環境がv4.5以降であれば良いのだろうか?

以下ではv2.0 SP1以降であればConnectAsync()が使えるような記載がされている。
https://stackoverflow.com/questions/5764921/whats-the-difference-between-beginconnect-and-connectasync

Prefer ConnectAsync when possible (though it requires min .NET 2.0 SP1).