ラベル C# の投稿を表示しています。 すべての投稿を表示
ラベル C# の投稿を表示しています。 すべての投稿を表示

2016年3月14日月曜日

EventHandlerの使い方

【発行側】
public class class1
{
   public delegate void _MyEvent(object sender, MyEventArgs e);
   public event _MyEvent MyEvent;
   protected virtual void MyChangeEvent(MyEventArgs e)
   {
      if ( MyEvent != null )
      {
         MyEvent( this, e );
      }
   }
   private void Changed()
   {
      MyEventArgs e = new MyEventArgs( arg1, arg2 );
      MyChangeEvent(e);
   }
   public class MyEventArgs : EventArgs
   {
      public string Arg1;
      public int Arg2;
      ...
      public MyEventArgs (  string _Arg1, int _Arg2 )
      {
         Arg1 = _Arg1;
         Arg2 = _Arg2;
      }
   }
}
【受取側】
public class class2
{
   private void Define()
   {
      class1 obj = new class1();
      obj.MyEvent += new class1._MyEvent(RecieveEvent);
    }
   private void RecieveEvent( object sender, class1.MyEventArgs e)
   {
      Console.WriteLine(e.Arg1 + e.Arg2);
   }
}

2016年3月8日火曜日

Wpf細かい書式

毎回忘れる細かい書式

・.Resource内での宣言
<.Resource>
     <DataTemplate DataType="{x:Type [namespace]:[class]}" />
</.Resource>

・ListBoxへのBinding
要素が1つなら
 <ListBox ItemsSource="{Binding [List]}" DisplayMemberPath="[Listの要素]"/>

要素が複数かつ色々変えるなら
<ListBox ItemsSource="{Binding [List]}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding [要素1]}"/>
                <TextBlock Text="{Binding [要素2]}"/>         
            </StackPanel>
         </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

選択できなくて良いなら
<ItemsControl ItemsSource="{Binding [List]}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border Background="LightPink" CornerRadius="20">
                <TextBlock Margin="1">
                                <!--Run Text="要素1 : " FontSize="10"/-->
                                <Run Text="{Binding [要素1]}" FontSize="10"/>
                                <LineBreak/>
                                <Run Text="要素2 : "/>
                                <Run Text="{Binding [要素2]}"/>
                </TextBlock>
            </Border>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

・PropertyChangedの通知
public event PropertyChangedEventHandler PropertyChanged;

 private void NotifyPropertyChanged(string info)
 {
     if (PropertyChanged != null)
     {
         PropertyChanged(this, new PropertyChangedEventArgs(info));
     }
 }

PasswordBoxでデータバインド

【参考】http://garafu.blogspot.jp/2014/09/wcf-passwordbox.html
セキュリティの問題から基本的には非推奨
-----------------------

利用方法
<PasswordBox [namespace]:PasswordBoxHelper.Password = {Binding Target}/>


------------------------
【PasswordBoxHelper.cs】

namespace WpfPasswordBox
{
    using System.Windows;
    using System.Windows.Controls;
    public class PasswordBoxHelper : DependencyObject
    {
        public static readonly DependencyProperty IsAttachedProperty = DependencyProperty.RegisterAttached(
            "IsAttached",
            typeof(bool),
            typeof(PasswordBoxHelper),
            new FrameworkPropertyMetadata(false, PasswordBoxHelper.IsAttachedProperty_Changed));
        public static readonly DependencyProperty PasswordProperty = DependencyProperty.RegisterAttached(
            "Password",
            typeof(string),
            typeof(PasswordBoxHelper),
            new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, PasswordBoxHelper.PasswordProperty_Changed));
        public static bool GetIsAttached(DependencyObject dp)
        {
            return (bool)dp.GetValue(PasswordBoxHelper.IsAttachedProperty);
        }
        public static string GetPassword(DependencyObject dp)
        {
            return (string)dp.GetValue(PasswordBoxHelper.PasswordProperty);
        }
        public static void SetIsAttached(DependencyObject dp, bool value)
        {
            dp.SetValue(PasswordBoxHelper.IsAttachedProperty, value);
        }
        public static void SetPassword(DependencyObject dp, string value)
        {
            dp.SetValue(PasswordBoxHelper.PasswordProperty, value);
        }
        private static void IsAttachedProperty_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var passwordBox = sender as PasswordBox;
            if ((bool)e.OldValue)
            {
                passwordBox.PasswordChanged -= PasswordBoxHelper.PasswordBox_PasswordChanged;
            }
            if ((bool)e.NewValue)
            {
                passwordBox.PasswordChanged += PasswordBoxHelper.PasswordBox_PasswordChanged;
            }
        }
        private static void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
        {
            var passwordBox = sender as PasswordBox;
            PasswordBoxHelper.SetPassword(passwordBox, passwordBox.Password);
        }
        private static void PasswordProperty_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var passwordBox = sender as PasswordBox;
            var newPassword = (string)e.NewValue;
            if (!GetIsAttached(passwordBox))
            {
                SetIsAttached(passwordBox, true);
            }
            if ((string.IsNullOrEmpty(passwordBox.Password) && string.IsNullOrEmpty(newPassword)) ||
                passwordBox.Password == newPassword)
            {
                return;
            }
            passwordBox.PasswordChanged -= PasswordBoxHelper.PasswordBox_PasswordChanged;
            passwordBox.Password = newPassword;
            passwordBox.PasswordChanged += PasswordBoxHelper.PasswordBox_PasswordChanged;
        }
    }
}

2016年2月29日月曜日

ViewModelBaseの代替?

【参考】http://zecl.hatenablog.com/entry/20091211/p1


 【IImpleNotifyPropertyChanged.cs】
using System;
using System.Linq;
using System.Linq.Expressions;
using System.ComponentModel;

namespace ClassLibrary1
{
    /// <summary>
    /// IImpleNotifyPropertyChangedインターフェイス
    /// 
    /// INotifyPropertyChangedの実装をある程度抽象化し、簡易な実装を提供します。
    /// </summary>
    public interface IImpleNotifyPropertyChanged : INotifyPropertyChanged
    {
        /// <summary>
        /// PropertyChangedの再定義
        /// (INotifyPropertyChangedのPropertyChangedを隠蔽する)
        /// </summary>
        new event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// PropertyChangedEventHandlerを取得します。
        /// </summary>
        PropertyChangedEventHandler PropertyChangedHandler { get; }
    }

    /// <summary>
    /// IImpleNotifyPropertyChangedインターフェイスについて拡張メソッド提供
    /// </summary>
    public static class IImpleNotifyPropertyChangedExtentions
    {
        /// <summary>
        /// プロパティの変更を通知します。
        /// </summary>
        /// <param name="self">対象</param>
        /// <param name="targets">プロパティ変更通知対象の名称群</param>
        private static void OnPropertyChanged<TObject>(this TObject self, params string[] propertyNames)
            where TObject : IImpleNotifyPropertyChanged
        {
            if (self == null) return;
            if (self.PropertyChangedHandler == null) return;

            foreach (var propertyName in propertyNames)
                self.PropertyChangedHandler(self, new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// プロパティの変更を通知します。
        /// </summary>
        /// <typeparam name="TObject"></typeparam>
        /// <typeparam name="TExpression"></typeparam>
        /// <param name="self">対象</param>
        /// <param name="expressions">プロパティ変更通知対象の名称を取得するExpression群</param>
        public static void OnPropertyChanged<TObject, TExpression>(this TObject self, params Expression<Func<TObject, TExpression>>[] expressions)
            where TObject : IImpleNotifyPropertyChanged
        {
            var propertyNames = from e in expressions
                                select ((MemberExpression)e.Body).Member.Name;
            self.OnPropertyChanged(propertyNames.ToArray());
        }
    }

    /// <summary>
    /// INotifyPropertyChangedインターフェイスについて拡張メソッドを提供
    /// </summary>
    public static class INotifyPropertyChangedExtentions
    {
        /// <summary>
        /// プロパティ変更イベントの関連付け補助
        /// </summary>
        /// <typeparam name="TObject"></typeparam>
        /// <typeparam name="TExpression"></typeparam>
        /// <param name="self"></param>
        /// <param name="expressions"></param>
        /// <param name="handler"></param>
        public static void AddPropertyChanged<TObject, TExpression>(this TObject self, Expression<Func<TObject, TExpression>> expressions, Action<TObject> handler)
            where TObject : INotifyPropertyChanged
        {
            if (self == null) return;
            var propName = ((MemberExpression)expressions.Body).Member.Name;
            self.PropertyChanged += (sender, e) =>
            {
                if (e.PropertyName == propName)
                    handler(self);
            };
        }
    }
}

RelayCommand.cs

【参考】http://d.hatena.ne.jp/kaorun/20141202/1417532472
 ICommandの簡単実装
--------------------------
 ViewModel内で宣言
・宣言    
public ICommand Event_name { get; set; }
・コンストラクタで初期化
Event_name = new RelayCommand( Process_name );
・実処理は別に作成(簡単な処理ならlambdaで)       
public void Process_name(){
   処理内容;
 (例:インクリメント、メッセージボックス表示)
}
--------------------------
Common内で定義
【RelayCommand.cs】
using System;
using System.Windows.Input;
namespace Project.Common
{
    public class RelayCommand : ICommand
    {
        private readonly Action _execute;
        private readonly Func<bool> _canExecute;

        public event EventHandler CanExecuteChanged;

        public RelayCommand(Action execute) : this(execute, null)
        {
        }
        public RelayCommand(Action execute, Func<bool> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
            _execute = execute;
            _canExecute = canExecute;
        }
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute();
        }
        public void Execute(object parameter)
        {
            _execute();
        }
        public void RaiseCanExecuteChanged()
        {
            var handler = CanExecuteChanged;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }

    }
}

2016年1月26日火曜日

非同期ソケット通信サーバー側


 試行錯誤中のゴミが大量混入ver
    class SocketServer
    {
        //ホスト名からIPアドレスを取得する時は、次のようにする
        //string host = "localhost";
        //System.Net.IPAddress ipAdd =
        //    System.Net.Dns.GetHostEntry(host).AddressList[0];
        //.NET Framework 1.1以前では、以下のようにする
        //System.Net.IPAddress ipAdd =
        //    System.Net.Dns.Resolve(host).AddressList[0];

        private System.Net.Sockets.TcpClient objSckClient;
        System.Net.Sockets.NetworkStream SendNS;
        private System.Net.Sockets.TcpListener objSckServer;
        private System.Threading.Thread ListeningCallbackThread;

        private volatile bool SLTAlive;
        private volatile bool SendAlive;

        public SocketServer()
        {
            objSckClient = new System.Net.Sockets.TcpClient();
            SLTAlive = false;
            SendAlive = false;
            //---------------------
            InvokeMethod = new InvokeMethodDelegate(BeginInvokeTypeMethod);
            Caller = new CommunicationCallbackDelegate(CommunicationCallback);
        }
        public void Recieve_Close()
        {
            if (SLTAlive)
            {
                SLTAlive = false;
                objSckServer.Stop();
                ListeningCallbackThread = null;
            }
        }
        public void Recieve_Stop()
        {
            if (objSckServer != null)
            {
                objSckServer.Stop();
            }
            SLTAlive = false;
            Console.WriteLine("サーバー正常終了");
        }
        public void Recieve_CreateThread()
        {
            SLTAlive = true;
            ListeningCallbackThread = new System.Threading.Thread(ListeningCallback);
            ListeningCallbackThread.Start();
        }
        private void ListeningCallback()
        {
            objSckServer = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Any, 12323);
            objSckServer.Start();
            Console.WriteLine("サーバー開始");
            try
            {
                int cnt = 0;
                while (SLTAlive)
                {
                    cnt++;
                    Console.WriteLine("1, " + cnt);
                    if (objSckServer.Pending())
                    {
                        Console.WriteLine("2, " + cnt);
                        System.Net.Sockets.TcpClient ClientSocket = objSckServer.AcceptTcpClient();
                        Console.WriteLine("connected : " + ((System.Net.IPEndPoint)ClientSocket.Client.RemoteEndPoint).Address + ", " + ((System.Net.IPEndPoint)ClientSocket.Client.RemoteEndPoint).Port);
                        System.Net.Sockets.NetworkStream stream = ClientSocket.GetStream();
                        byte[] RecieveData = new Byte[2000];
                        int DataLength = stream.Read(RecieveData, 0, RecieveData.Length);
                        string str = System.Text.Encoding.Unicode.GetString(RecieveData, 0, DataLength);
                        Console.WriteLine("受け取り手:" + str);

                        byte[] SendBuffer = System.Text.Encoding.Unicode.GetBytes("サーバーメッセージ");
                        stream.Write(SendBuffer, 0, SendBuffer.Length);
                        stream.Flush();
                        ClientSocket.Close();
                    }
                    System.Threading.Thread.Sleep(100);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
        public void Send_Connect()
        {
            objSckClient.Connect("127.0.0.1", 12323);
            Console.WriteLine("サーバー({0}:{1})と接続しました({2}:{3})。", ((System.Net.IPEndPoint)objSckClient.Client.RemoteEndPoint).Address, ((System.Net.IPEndPoint)objSckClient.Client.RemoteEndPoint).Port, ((System.Net.IPEndPoint)objSckClient.Client.LocalEndPoint).Address, ((System.Net.IPEndPoint)objSckClient.Client.LocalEndPoint).Port);

            SendNS = objSckClient.GetStream();
            SendNS.ReadTimeout = 10000; //10sec
            SendNS.WriteTimeout = 10000; //*1ms
            SendAlive = true;
        }
        public void Send_Execute()
        {
            if (SendAlive)
            {
                String SendMessage = "メッセージ送信";
                byte[] sendBytes = System.Text.Encoding.Unicode.GetBytes(SendMessage + "\n");
                SendNS.Write(sendBytes, 0, sendBytes.Length);
                Console.WriteLine("送り手:メッセージ送信済");
            }

        }
        public void Send_Close()
        {
            if (SendAlive)
            {
                SendNS.Close();
                objSckClient.Close();
                Console.WriteLine("クライアントとの接続終了");
            }
        }

  //--------------------------------------------------------------------------------------------------------------
        //メンバ変数

        // 送受信電文処理スレッド呼び出し用オブジェクト
        private CommunicationCallbackDelegate Caller;

        // 送受信電文処理メソッド用デリゲート
        delegate ProcessingResultOfCommunication CommunicationCallbackDelegate(System.Net.Sockets.TcpListener listener);

        // 待機中のスレッドを管理するオブジェクト
        public static System.Threading.ManualResetEvent AllDone = new System.Threading.ManualResetEvent(false);

        //----------------------------------------------------------------------------------------------------------------

        public class ProcessingResultOfCommunication
        {
            public string ReceivedData; // 受信データ
            public string Reply; // 返信(送信データ)
        }
       //----------------------------------------------------------------------------------------------------------------
        public void Recieve_Start2()
        {
            if (!SLTAlive)  // まだ接続待ちスレッドを生成していない場合
            {

                // リスナー(接続要求受け入れ待機)を生成
                objSckServer = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Parse("127.0.0.1"), 12323);
                // *** server = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Any, 9000);

                // 接続要求受け入れ開始
                objSckServer.Start();

                // 接続待ち用スレッドを作成
                ListeningCallbackThread = new System.Threading.Thread(ListeningCallback2);

                // 接続待ち用スレッドを開始
                ListeningCallbackThread.Start();

                // スレッド終了指示フラグを未終了に設定
                SLTAlive = true;
            }
        }

        // ************************************
        // 接続待ちスレッド用メソッド
        //  --- クライアントからの受信受け付けを行なうメソッドです。なお、受信受
        //      け付けを常に行なうため、無限ループで受け付け処理を行っています。
        //      無限ループは、処理を占有して、本サーバープログラム自体の動作に影
        //      響しますので、本メソッドは、スレッドとして起動します。
        // ************************************
        private void ListeningCallback2()
        {

            //            label1.Text = "サーバー開始";
            Console.WriteLine("サーバー開始");

            try
            {

                // 受信の受付を行なうための無限ループ
                while (SLTAlive)    // スレッド終了指示フラグでの終了指示がある場合はループ終了
                {

                    // 受信接続キュー内で、接続待ちがあるか判断
                    if (objSckServer.Pending() == true)
                    {

                        // AllDoneを非シグナル状態にする
                        // すなわち、スレッドの実行指示の状態をリセットして戻す。
                        AllDone.Reset();

                        // スレッドを起動し、送受信電文処理スレッド用メソッドを実行します。
                        InvokeMethod();


                        // AllDoneがシグナル状態になるまでスレッドをブロック。
                        // すなわち、送受信電文処理用スレッドから、実行開始の指示が出るまで待機する。
                        AllDone.WaitOne();

                    }

                    // 短時間だけ待機
                    System.Threading.Thread.Sleep(100);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("サーバー終了\n" + ex);
            }
        }
        //----------------------------------------------------------------------------------------------------------------
        //========================
        // 電文処理スレッド起動メソッド用デリゲート
        //========================

        delegate void InvokeMethodDelegate();
        private InvokeMethodDelegate InvokeMethod;

        //----------------------------------------------------------------------------------------------------------------
        // ************************************
        // 送受信電文処理スレッド用メソッド
        //  --- 受信された電文に対して、具体的な処理を行なうメソッドです。このサ
        //      ンプルでは、受信電文をテキストボックスに表示し、また、クライアン
        //      トへ返信を返す処理としています。
        //      なお、本メソッド(電文処理部)は、複数のクライアントからの接続に対
        //      応しています。すなわち、受信があるたびにスレッドが起動し、本メソ
        //      ッドが実行されます。
        // 第1引数: クライアントからの受信接続要求を処理するリスナー
        // 戻り値: 処理結果
        // ************************************
        public ProcessingResultOfCommunication CommunicationCallback(System.Net.Sockets.TcpListener listener)
        {

            // AllDoneをシグナル状態にする。
            // すなわち、接続待ちスレッドのロックを解除して、接続待ちスレッドの実行再開の許可をする。
            AllDone.Set();


            // 処理結果格納用クラスの生成
            ProcessingResultOfCommunication ResultData = new ProcessingResultOfCommunication();


            if (SLTAlive)  // 接続待ちスレッドが作成されていて使える場合
            {
                try
                {
                    // クライアントからの接続を受け付ける
                    System.Net.Sockets.TcpClient ClientSocket = listener.AcceptTcpClient(); // TCPクライアント

                    // 通信ストリームの取得
                    System.Net.Sockets.NetworkStream stream = ClientSocket.GetStream();

                    //============
                    // クライアントからの電文の受信
                    byte[] ReceiveData = new byte[2000];
                    int DataLength = stream.Read(ReceiveData, 0, ReceiveData.Length);   // 電文の列長
                    string str = System.Text.Encoding.Unicode.GetString(ReceiveData, 0, DataLength);
                    //============
                    // 処理結果格納用クラスに本メソッドの処理結果を格納

                    // 受信データーを処理結果格納用クラスに設定
                    ResultData.ReceivedData = str;

                    // 返信データーの作成
                    ResultData.Reply = "通信データー<< " + str + ">>を受け取りました。";
                    //============
                    // サーバーで処理時間のかかる処理が行なわれる場合を、仮に実験したい
                    // 場合は、下記の時間待機のメソッドを実行させて下さい。
                    // *** System.Threading.Thread.Sleep(30000);



                    //============
                    // 返信電文をクライアントへ送信
                    byte[] SendBuffer = System.Text.Encoding.Unicode.GetBytes(ResultData.Reply);
                    stream.Write(SendBuffer, 0, SendBuffer.Length);
                    stream.Flush(); // フラッシュ(強制書き出し)

                    // 通信ストリームをクローズ
                    stream.Close();

                    // TCPクライアントをクローズ
                    ClientSocket.Close();

                }
                catch (Exception ex)
                {
                }


            }

            return ResultData;

        }
        //------------------------------------------------------------------------------------------




        //========================
        // ノンブロッキング通信指定時に使われるメソッド
        //========================

        //========================
        // ノンブロッキング通信指定時の電文処理スレッド起動用メソッド
        private void BeginInvokeTypeMethod()
        {

            // ワーカースレッドでの処理終了時に起動するコールバックメソッドを指定
            AsyncCallback asc = new AsyncCallback(ReturnCallback);

            // スレッドを起動し、送受信電文処理スレッド用メソッドを実行します。
            IAsyncResult AsyRes = Caller.BeginInvoke(objSckServer, asc, null);
            //IAsyncResult AsyRes = Caller.BeginInvoke(ServerSocket, asc, new object[] { ServerSocket });

        }

        //========================
        // スレッド完了時起動のコールバックメソッド
        // BeginInvokeでの呼び出し(非同期呼び出し)で起動されるスレッドにおいて、
        // その処理が完了した時に、呼び出し元に呼び出されるメソッドです。
        // よって、ワーカースレッド(BeginInvokeで呼び出されるスレッド)での処理
        // 結果に関する処理等をここに定義すると便利です。
        // 第1引数: 非同期デリゲートでの非同期操作の結果(をカプセル化した物)
        public void ReturnCallback(IAsyncResult AsyRes)
        {

            // 結果を取り出すための非同期結果のキャスト。
            System.Runtime.Remoting.Messaging.AsyncResult aResult = (System.Runtime.Remoting.Messaging.AsyncResult)AsyRes;

            // 非同期の呼び出しが行われたデリゲート オブジェクトを取得。
            CommunicationCallbackDelegate dele = (CommunicationCallbackDelegate)aResult.AsyncDelegate;

            // デリゲートの完了処理を実行。及びワーカースレッドでの処理結果の受け取り。
            ProcessingResultOfCommunication ResultData = dele.EndInvoke(AsyRes);

            // 受信データを表示
            //textBox1.Text += ResultData.ReceivedData + "\r\n";
            Console.WriteLine(ResultData.ReceivedData);

        }
    }
【参考】http://note.chiebukuro.yahoo.co.jp/detail/n26284

ソケット通信クライアント側


    class SocketClient2
    {
        public SocketClient2() { }
        public void mai(String ipOrHost, int port, String sendMsg)
        {
            if (sendMsg == null || sendMsg.Length == 0)
            {
                return;
            }

            //TcpClientを作成し、サーバーと接続する
            System.Net.Sockets.TcpClient tcp =
                new System.Net.Sockets.TcpClient(ipOrHost, port);
            Console.WriteLine("サーバー({0}:{1})と接続しました({2}:{3})。",
                ((System.Net.IPEndPoint)tcp.Client.RemoteEndPoint).Address,
                ((System.Net.IPEndPoint)tcp.Client.RemoteEndPoint).Port,
                ((System.Net.IPEndPoint)tcp.Client.LocalEndPoint).Address,
                ((System.Net.IPEndPoint)tcp.Client.LocalEndPoint).Port);

            //NetworkStreamを取得する
            System.Net.Sockets.NetworkStream ns = tcp.GetStream();

            //読み取り、書き込みのタイムアウトを10秒にする
            //デフォルトはInfiniteで、タイムアウトしない
            //(.NET Framework 2.0以上が必要)
            ns.ReadTimeout = 10000;
            ns.WriteTimeout = 10000;

            //サーバーにデータを送信する
            //文字列をByte型配列に変換
            //System.Text.Encoding enc = System.Text.Encoding.UTF8;
            System.Text.Encoding enc = System.Text.Encoding.Unicode;
            byte[] sendBytes = enc.GetBytes(sendMsg + '\n');
            //データを送信する
            ns.Write(sendBytes, 0, sendBytes.Length);
            Console.WriteLine(sendMsg);

            //サーバーから送られたデータを受信する
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            byte[] resBytes = new byte[256];
            int resSize = 0;
            do
            {
                //データの一部を受信する
                resSize = ns.Read(resBytes, 0, resBytes.Length);
                //Readが0を返した時はサーバーが切断したと判断
                if (resSize == 0)
                {
                    Console.WriteLine("サーバーが切断しました。");
                    break;
                }
                //受信したデータを蓄積する
                ms.Write(resBytes, 0, resSize);
                //まだ読み取れるデータがあるか、データの最後が\nでない時は、
                // 受信を続ける
            } while (ns.DataAvailable || resBytes[resSize - 1] != '\n');
            //受信したデータを文字列に変換
            string resMsg = enc.GetString(ms.GetBuffer(), 0, (int)ms.Length);
            ms.Close();
            //末尾の\nを削除
            resMsg = resMsg.TrimEnd('\n');
            Console.WriteLine(resMsg);

            //閉じる
            ns.Close();
            tcp.Close();
        }
    }
【参考】http://dobon.net/vb/dotnet/internet/tcpclientserver.html