HOW DO I ソケットで通信を行うには ここでは以下の手順で説明します ソケットクライアントを作成するデータを送信するデータを受信するソケットクライアントを使用する ソケットクライアントを作成する 1. このコンテンツのサポートファイルの Start フォルダから "UDPClient" プロジェクトを開きます 2. クライアントを動作させるため コンピューターで簡易 TCP/IP サービスを有効にする必要があります 以下の手順を実行します a. コントロールパネルで [ プログラムと機能 ] を開きます b. [Windows の機能の有効化または無効化 ] をクリックします c. [Windows の機能 ] ダイアログで [ 簡易 TCP/IP サービス ] チェックボックスをオンにして機能を有効にし [OK] をクリックします d. この手順を実行するには ローカルコンピューターの Administrators グループまたは Network Configuration Operators グループのメンバーとしてログオンする必要があります e. コンピューターの [ サービス ] リストで "Simple TCP/IP Services" サービスが開始されていることを確認します 開始されていない場合はサービスを手動で開始します サービスの開始方法の詳細については サービスの開始方法を構成する を参照してください 3. メニューから [ プロジェクト ] [ クラスの追加 ] を選択し SocketClient という名前を付けます 4. SocketClient.cs で System.Net.Sockets System.Threading System.Text の名前空間を追加し SocketClient クラスに以下のメンバー変数を定義します using System.Net.Sockets; using System.Threading; using System.Text;
// このクラスの有効期間中の各呼び出しに使用される キャッシュされた Socket オブジェクト Socket socket = null; // 非同期処理が完了したことを通知するために信号を送るオブジェクト static ManualResetEvent clientdone = new ManualResetEvent(false); // 各非同期呼び出しのタイムアウトをミリ秒で定義する このタイムアウト期間内に // 応答を受信しなかった場合 呼び出しが中止される const int TIMEOUT_MILLISECONDS = 5000; // 非同期ソケットメソッドで使用するデータバッファーの最大サイズ const int MAX_BUFFER_SIZE = 2048; 5. 以下のパラメーターを使って socket 変数を初期化するコンストラクターを追加します public SocketClient() // AddressFamily.InterNetwork - ソケットは IP version 4 アドレス指定方式を // 使用してアドレスを解決する // SocketType.Dgram - データグラム ( メッセージ ) パケットをサポートするソケット // PrototcolType.Udp - ユーザーデータグラムプロトコル (UDP) socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 6. socket を閉じる Close メソッドを追加します public void Close() socket.close(); データを送信する 1. SocketClient.cs で Send メソッドを追加します 文字列を返すようにし パラメーター として servername portnumber data を受け入れます
public string Send(string servername, int portnumber, string data) 2. Send メソッドで string 型の変数 response を定義し 既定値として "Operation Timeout" を設定します string response = "Operation Timeout"; 3. ソケットが null でないかどうか確認し 以下のようにデータを送信します if (socket!= null) // SocketAsyncEventArgs コンテキストオブジェクトを作成する SocketAsyncEventArgs socketeventarg = new SocketAsyncEventArgs(); // コンテキストオブジェクトのプロパティを設定する socketeventarg.remoteendpoint = new DnsEndPoint(serverName, portnumber); // Completed イベントのインラインイベントハンドラー // 注 : メソッドを自己完結させるため このイベントハンドラーはインラインで実装される socketeventarg.completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) response = e.socketerror.tostring(); // UI スレッドのブロックを解除する clientdone.set(); ); // 送信するデータをバッファーに追加する byte[] payload = Encoding.UTF8.GetBytes(data); socketeventarg.setbuffer(payload, 0, payload.length); // イベントの状態をシグナルなしに設定し スレッドのブロックを発生させる clientdone.reset(); // ソケットを使用して非同期の送信要求を行う socket.sendtoasync(socketeventarg); // TIMEOUT_MILLISECONDS の最大秒数まで UI スレッドをブロックする // この時間内に応答がなければ 処理を先に進める clientdone.waitone(timeout_milliseconds);
else response = "Socket is not initialized"; 4. 応答を返します return response; データを受信する 1. SocketClient.cs で Receive メソッドを追加します 文字列を返すようにし パラメータ ーとして portnumber を受け入れます public string Receive(int portnumber) 2. Receive メソッドで string 型の変数 response を定義し 既定値として "Operation Timeout" を設定します string response = "Operation Timeout"; 3. ソケットが null でないかどうか確認し 以下のようにデータを受信します if (socket!= null) // SocketAsyncEventArgs コンテキストオブジェクトを作成する SocketAsyncEventArgs socketeventarg = new SocketAsyncEventArgs(); socketeventarg.remoteendpoint = new IPEndPoint(IPAddress.Any, portnumber); // データを受信するためのバッファーを設定する socketeventarg.setbuffer(new Byte[MAX_BUFFER_SIZE], 0, MAX_BUFFER_SIZE); // Completed イベントのインラインイベントハンドラー // 注 : メソッドを自己完結させるため このイベントハンドラーはインラインで実装される socketeventarg.completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) if (e.socketerror == SocketError.Success)
// バッファーからデータを取得する response = Encoding.UTF8.GetString(e.Buffer, e.offset, e.bytestransferred); response = response.trim('\0'); else response = e.socketerror.tostring(); ); clientdone.set(); // イベントの状態をシグナルなしに設定し スレッドのブロックを発生させる clientdone.reset(); // ソケットを使用して非同期の受信要求を行う socket.receivefromasync(socketeventarg); // TIMEOUT_MILLISECONDS の最大秒数まで UI スレッドをブロックする // この時間内に応答がなければ 処理を先に進める clientdone.waitone(timeout_milliseconds); else response = "Socket is not initialized"; 4. 応答を返します return response; ソケットクライアントを使用する 1. MainPage.xaml.cs の btnecho の Click イベントハンドラーで ClearLog の後に client という名前の新しい SocketClient 変数を作成します SocketClient client = new SocketClient(); 2. 以下のように エコーされるメッセージを送信します Log(String.Format(">> Sending '0' to server...", txtinput.text)); string result = client.send(txtremotehost.text, ECHO_PORT, txtinput.text); 3. 以下のように 応答を受信してクライアントを閉じます
Log(">> Requesting receive..."); result = client.receive(echo_port); client.close(); 1. MainPage.xaml.cs の btngetquote の Click イベントハンドラーで client という名前の新 しい SocketClient 変数を ClearLog の後に作成します SocketClient client = new SocketClient(); 2. 以下のように 今日の名言 (quote of the day) の要求を送信します // UDP では 着信する UDP メッセージごとにメッセージが送信されるため " ダミー " メッセージを送信して // 応答を求める メッセージは空にできないので 以下のメッセージは空白文字 1 つで構成されている Log(">> Requesting quote"); string result = client.send(txtremotehost.text, QOTD_PORT, " "); 3. 以下のように 応答を受信してクライアントを閉じます // " 今日の名言 " (QOTD) を返すサーバーからの応答を受信する Log(">> Requesting receive..."); result = client.receive(qotd_port); client.close(); 4. プロジェクトを実行します 5. [Host Name] に利用しているコンピュータ名または現在割り当てられている IP アドレスを入力します 6. エコーするテキストを追加して [Echo] ボタンをタップします 応答が出力テキストボックスに返されることを確認します 7. [Get Quote of the Day] ボタンをタップします 応答が出力テキストボックスに返されることを確認します インターネットおよびその他のサービスとのほぼリアルタイムな通信を可能にする 新しいソケット機能を紹介しました
参考ビデオ : How Do I: Communicate with Sockets in Windows Phone Mango? http://msdn.microsoft.com/en-us/hh329472