Visual Studio | WPF > TCPサーバ > echo server > 1対1通信 >Thread処理 | link: 自分のIPアドレスを取得する

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

WPFでTCP echo serverを実装してみる。

### 参考

- [Visual Studio / WPF > UDP > echo server > v0.1](https://qiita.com/7of9/items/dc3cb128bcc2766cdf78)
- [TcpListener クラス](https://msdn.microsoft.com/ja-jp/library/system.net.sockets.tcplistener(v=vs.110).aspx)
- [TcpClient クラス](https://msdn.microsoft.com/ja-jp/library/system.net.sockets.tcpclient(v=vs.110).aspx)
- [How to get all data from NetworkStream](https://stackoverflow.com/questions/26058594/how-to-get-all-data-from-networkstream)
- [TCPクライアント・サーバープログラムを作成する](https://dobon.net/vb/dotnet/internet/tcpclientserver.html)
- [Tcp client: Use StreamReader and StreamWriter to read and write to a server : NetworkStream « Network « C# / CSharp Tutorial](http://www.java2s.com/Tutorial/CSharp/0580__Network/TcpclientUseStreamReaderandStreamWritertoreadandwritetoaserver.htm)

### 処理概要

- 自分のIPアドレスを取得する
    - https://stackoverflow.com/questions/6803073/get-local-ip-address
- 自分のIPアドレスでTcpListenerを開始する
- スレッドで受信処理を行う
    - ReadLine()使用
- 受信したらecho backする

### code

```MainWindow.xaml
<Window x:Class="_171204_t1710_TCPechoServer.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:_171204_t1710_TCPechoServer"
        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.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace _171204_t1710_TCPechoServer
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {

        private Thread rcvThr;
        TcpListener tcpListener;
        private readonly int kPort_recv = 7000;
        private bool stopThr = false;

        public MainWindow()
        {
            InitializeComponent();
        }

        private static string getMyIpaddress()
        {
            var host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    return ip.ToString();
                }
            }
            return null;
        }

        private void B_connect_Click(object sender, RoutedEventArgs e)
        {
            this.Title = "Connected";

            string ipstr = getMyIpaddress();
            System.Net.IPAddress ipadr = System.Net.IPAddress.Parse(ipstr);
            tcpListener = new TcpListener(ipadr, kPort_recv);
            tcpListener.Start();

            rcvThr = new Thread(new ThreadStart(FuncRcvData));
            rcvThr.Start();
        }

        private void FuncRcvData()
        {
            while (stopThr == false)
            {
                TcpClient client = tcpListener.AcceptTcpClient();

                if (client.Connected == false)
                {
                    continue;
                }
                using (var netStream = client.GetStream())
                {
                    using (var sReader = new StreamReader(netStream, Encoding.UTF8))
                    {
                        var sWriter = new StreamWriter(netStream, Encoding.UTF8);

                        do
                        {
                            string str = sReader.ReadLine();
                            if (str == null)
                            {
                                break;
                            }
                            sWriter.WriteLine(str);
                            sWriter.Flush();
                            //
                            Console.WriteLine(str);
                        } while (true);
                        sWriter.Close();
                    }
                }
                client.Close();
            }
        }
    }
}
```

### 動作確認

NonSoftさんの[「TCP/IPテストツール」](http://nonsoft.la.coocan.jp/Download/SocketTool/index.html)にて動作確認しました。
提供感謝です。

### 気づいた事項

- ~~127.0.0.1では受信できない~~
    - ~~自分のIPアドレスが必要~~
    - ~~そのため自分のIPアドレス取得方法を探した~~
    - `tcpListener = new TcpListener(IPAddress.Any, kPort_recv);`で良かった。
- WriteLine()でecho backするときはFlush()をコールする

### 改善点

１つのクライアントと接続中に別のクライアントへの応答ができない。