チャットアプリ

Similar documents
プラグイン

ファイル操作-バイナリファイル

ICONファイルフォーマット

プロセス間通信

// このクラスの有効期間中の各呼び出しに使用される キャッシュされた Socket オブジェクト Socket socket = null; // 非同期処理が完了したことを通知するために信号を送るオブジェクト static ManualResetEvent clientdone = new Ma

NotifyIconコントロール

正規表現応用

データアダプタ概要

ハッシュテーブル

mySQLの利用

構造体

ListViewコントロール

VB.NET解説

ファイル操作

Visual Basic 資料 電脳梁山泊烏賊塾 コレクション初期化子 コレクション初期化子 初めに.NET 版の Visual Basic では 其れ迄の Visual Basic 6.0 とは異なり 下記の例の様に変数宣言の構文に 初期値を代入する式が書ける様に成った 其の際 1 の様に単一の値

グラフィックス

ファイル監視

12.1 インターネットアドレス インターネットアドレス インターネットアドレス 32 ビットの長さを持つインターネットに接続されたマシンを識別するのに使う インターネットアドレスは ピリオドで区切られたトークンの並びで表現されることもある インターネットアドレス

データベースプログラミング

Userコントロール

ファイル操作-インターネットキャッシュ

VB 資料 電脳梁山泊烏賊塾 音声認識 System.Speech の利用 System.Speech に依るディクテーション ( 音声を文字列化 ).NetFramework3.0 以上 (Visual Studio 2010 以降 ) では 標準で System.Speech が用意されて居るの

PYTHON 資料 電脳梁山泊烏賊塾 PYTHON 入門 関数とメソッド 関数とメソッド Python には関数 (function) とメソッド (method) が有る モジュール内に def で定義されて居る物が関数 クラス内に def で定義されて居る物がメソッドに成る ( 正確にはクラスが

チャットプログラム

ルーレットプログラム

DAOの利用

ウィンドウ操作 応用

PowerPoint Presentation

メール送信

.NETプログラマー早期育成ドリル ~VB編 付録 文法早見表~

Microsoft Excel操作

MISAO with WPF

VB実用Ⅲ⑩ フリーデータベースⅡ

スレッド操作 タイマー

メール受信

LogisticaTRUCKServer-Ⅱ距離計算サーバ/Active-Xコントロール/クライアント 概略   

通信対戦プログラム

ブロック パニック

回文作成支援プログラム

モグラ叩きプログラム

PYTHON 資料 電脳梁山泊烏賊塾 PYTHON 入門 文字列 文字列リテラル プログラムの中で文字列を表す方法は幾つか有るが 基本的な方法は下記の 2 種で有る 対象と成る文字の集まりをダブルクオーテーション ( " ) で囲うか シングルクオーテーション ( ' ) で囲う PYTHON3 "

ADO.NETのアーキテクチャ

Network Programming

ブロック崩し風テニス

Android Layout SDK プログラミング マニュアル

(Microsoft PowerPoint - \223\306\217KJava\221\346\202R\224\305.ppt)

データベースⅠ

ASP.NET 2.0 Provider Model 概要

Prog1_10th

構造体

GEC-Java

データベース1

Secure iNetSuite for .NET 4.0Jの新仕様について

Prog1_6th

C 資料 電脳梁山泊烏賊塾 キャスト C++ のキャスト 初めに 此処では Visual Studio 2017 を起動し 新しいプロジェクトで Visual C++ の Windows デスクトップを選択し Windows コンソールアプリケーションを作成する C++ でのキャスト

正規表現概要

XML(DOMガイド)

アセンブラ C# で作られたプログラムをデコンパイル デコンパイルとは 大雑把に言うと コンパイルされたプログラム (exe dll 等 ) から 元のコードを復元する行為の事で有る 特に C# や Java の様に中間言語に翻訳された状態でコンパイルされる様な言語の場合は元のコードに可成り忠実に復

データベース1

C 資料 電脳梁山泊烏賊塾 構造体 C++ の構造体 初めに 此処では Visual Studio 2017 を起動し 新しいプロジェクトで Visual C++ の Windows デスクトップを選択し Windows コンソールアプリケーションを作成する 定義と変数宣言 C++ に

テキストファイルの入出力1

基礎計算機演習 実習課題No6

TestDesign for Web

VB実用⑦ エクセル操作Ⅰ

Microsoft Word - IPC-intro.docx

チャットプログラム

データベース1

承 認

Microsoft PowerPoint ppt

プログラミング基礎I(再)

CashDrawer ライブラリ API 仕様書 2014/07/09 CashDrawer ライブラリ API 仕様書 Rev / 10

intra-mart Accel Platform — IM-Repository拡張プログラミングガイド   初版  

64bit環境で32bitコンポーネントの利用

グラフィックス 目次

相性占いプログラム

コードページ

VB.NET解説

相性占いプログラム

MS Office オートメーション

多言語ドメイン名の実装 mdnkit 石曽根信 ( 株 ) SRA 2001/12/04 日本語ドメイン名解説 / mdnkit 1 mdnkit 多言語ドメイン名を扱うためのツールキット 正規化 エンコード変換等を提供するライブラリとコマンド 既存アプリケーシ

Java の ConcurrentHashMap における同期化 バッドケースとその対処法 2013 年 9 月湊隆行 1. はじめに表 1.1 に示すように Java の Collections Framework には 3 つの世代があります バージョン 1.0 から存在するレガシー API バ

万年暦プログラム

占領双六ゲーム

ICONファイルフォーマット

Prog2_15th


UIOUSBCOM.DLLコマンドリファレンス

PYTHON 資料 電脳梁山泊烏賊塾 PYTHON 入門 ゲームプログラミング スプライト スプライト Pygame では pygame.sprite を用いる事でスプライトの管理 描画 衝突判定等を簡単に行う事が出来る 此れを利用してキャラクター操作に関する各種機能をスプライトクラスとして 1 個

回文作成支援プログラム

スケジューリングソルバScNurse

インベーダープログラム

チャットプログラム

Android プログラム ガイド

回文作成支援プログラム

オブジェクト指向プログラミング・同演習 5月21日演習課題

Socketクラス

1.SqlCtl クラスリファレンス SqlCtl クラスのリファレンスを以下に示します メソッドの実行中にエラーが発生した場合は標準エラー出力にメッセージを出力します (1)Connect() メソッド データベースへ connect 要求を行います boolean Connect(String

エクセル詳細 アドイン

1013  動的解析によるBOTコマンドの自動抽出

Java - Visual Editor

Transcription:

チャットアプリ Socket クラスに依る TCP 非同期通信の方法 複数のクライアントが同時に接続出来る TCP を利用したクライアントサーバー型チャットアプリケーションを TcpClient と TcpListener クラスを使わずに Socket クラスを使って作る方法を紹介する 初めに 此処では 複数のクライアントが同時に接続出来る TCP を利用したクライアントサーバー型チャットアプリケーション (DOBON Chat) のサンプルを示し 其の要点を解説する.NET Framework では TCP を利用したデータ通信を行う為のクラスとして TcpClient 及び TcpListener クラス ( 共に System.Net.Sockets 名前空間 ) が用意されて居る 此等のクラスは内部で Socket クラス (System.Net.Sockets 名前空間 ) を使用して居り Socket クラスをより簡単に扱える様にする為のクラスで有ると謂える 併し Socket クラスを直接扱う場合と比べて機能的に劣り 而も取り扱いの難しさも然程変わらない 其処で此処では TcpClient と TcpListener クラスを使わずに Socket クラスを使ってサーバーとクライアントを作成して居る (TcpClient と TcpListener を使用した簡単なサンプルは DOBON.NET.NET Tips - TCP クライアント サーバープログラムを作成する に有る ) 対象読者.NET でのネットワークプログラミング ( 特にソケットを使った TCP 非同期通信 ) に興味が有る方を対象として居る 但し 此処ではネットワークや.NET プログラミングの基本的な事柄に付いては説明しないので 不明な点は MSDN ライブラリ等で調べて欲しい -1-

必要な環境 サンプル (DobonChat) は Visual Studio.NET 2003 で作成され.NET Framework 1.1 で動作確認をして居るが.NET Framework 1.0 でも問題なく動作すると思う クライアントの作成 クライアントはサーバーに接続し データの送受信を行う Socket クラスの場合 データの送信には Send 受信には Receive メソッドを使えば簡単で有る ( 巻末に一例が有る ) 併し チャットアプリケーションの場合 少なくとも Receive メソッドを其の儘呼び出す訳には行かない Receive メソッドはデータを受信する迄スレッドをブロックする為 ( ブロッキングモードの場合 ) 其の間データの送信はおろか 何も出来なく成る 何時データが送られて来るか解らないチャットでは常にデータの受信を待機して居なければ成らない為 此れは致命的で有る データの受信を待機しつゝ 送信も出来る様にするには ポーリングに依る方法 ( 参考資料 3) や Socket クラスの非同期メソッドに依る方法 ( 参考資料 1,2) が有る ポーリングに依る方法では Socket.Poll メソッド ( 又は Available プロパティ ) でデータの読み取りが可能かループやタイマーで監視し 読み取れると判断出来れば Receive メソッドで受信する様にする ポーリングは此の様に無駄なループを繰り返す為 CPU に負担を懸けると謂う欠点が有る 一方非同期メソッドに依る方法では Socket の BeginReceive と EndReceive メソッドを使用する 此処では此の方法を採用して居る 非同期受信では 先ず BeginReceive メソッドを呼び出す事に依り データの受信が開始される Receive メソッドではデータを受信しない限り処理が次へ進まないが BeginReceive メソッドは直ぐに終了し ブロックしない BeginReceive を呼び出した後にデータを受信すると 指定したコールバックメソッドが実行される 此のコールバックメソッドで EndReceive メソッドを呼び出し データを受信し 再び BeginReceive メソッドを呼び出して非同期受信を再開する様にする 以下に非同期メソッドを使ってデータを受信する簡単な例を示す Connect メソッドを使って既にサーバーと接続して居る Socket を此の StartReceive メソッドに渡す事に依り データの非同期受信が開始され データを受信すると UTF-8 でデコードし コンソールに出力して居る VB ' 非同期データ受信の為の状態オブジェクト Private Class AsyncStateObject Public Socket As System.Net.Sockets.Socket Public ReceiveBuffer() As Byte Public ReceivedData As System.IO.MemoryStream Public Sub New(ByVal soc As System.Net.Sockets.Socket) Me.Socket = soc Me.ReceiveBuffer = New Byte(1023) Me.ReceivedData = New System.IO.MemoryStream End Sub End Class ' データ受信スタート -2-

Private Shared Sub StartReceive _ (ByVal soc As System.Net.Sockets.Socket) Dim so As New AsyncStateObject(soc) ' 非同期受信を開始 soc.beginreceive(so.receivebuffer, 0, so.receivebuffer.length, _ System.Net.Sockets.SocketFlags.None, _ New System.AsyncCallback(AddressOf ReceiveDataCallback), so) End Sub ' BeginReceive のコールバック Private Shared Sub ReceiveDataCallback(ByVal ar As System.IAsyncResult) ' 状態オブジェクトの取得 Dim so As AsyncStateObject = CType(ar.AsyncState, AsyncStateObject) ' 読み込んだ長さを取得 Dim len As Integer = 0 Try len = so.socket.endreceive(ar) Catch ex As System.ObjectDisposedException ' 閉じた時 System.Console.WriteLine(" 閉じました ") Return End Try ' 切断されたか調べる If len <= 0 Then System.Console.WriteLine(" 切断されました ") so.socket.close() Return End If ' 受信したデータを蓄積する so.receiveddata.write(so.receivebuffer, 0, len) If so.socket.available = 0 Then ' 最後迄受信した時 受信したデータを文字列に変換 Dim str As String = _ System.Text.Encoding.UTF8.GetString(so.ReceivedData.ToArray()) ' 受信した文字列を表示 System.Console.WriteLine(str) so.receiveddata.close() so.receiveddata = New System.IO.MemoryStream End If ' 再び受信開始 so.socket.beginreceive(so.receivebuffer, 0, _ so.receivebuffer.length, _ System.Net.Sockets.SocketFlags.None, _ New System.AsyncCallback(AddressOf ReceiveDataCallback), so) -3-

End Sub C# // 非同期データ受信の為の状態オブジェクト private class AsyncStateObject public System.Net.Sockets.Socket Socket; public byte[] ReceiveBuffer; public System.IO.MemoryStream ReceivedData; public AsyncStateObject(System.Net.Sockets.Socket soc) this.socket = soc; this.receivebuffer = new byte[1024]; this.receiveddata = new System.IO.MemoryStream(); // データ受信スタート private static void StartReceive(System.Net.Sockets.Socket soc) AsyncStateObject so = new AsyncStateObject(soc); // 非同期受信を開始 soc.beginreceive(so.receivebuffer, 0, so.receivebuffer.length, System.Net.Sockets.SocketFlags.None, new System.AsyncCallback(ReceiveDataCallback), so); // BeginReceive のコールバック private static void ReceiveDataCallback(System.IAsyncResult ar) // 状態オブジェクトの取得 AsyncStateObject so = (AsyncStateObject) ar.asyncstate; // 読み込んだ長さを取得 int len = 0; try len = so.socket.endreceive(ar); catch (System.ObjectDisposedException) // 閉じた時 System.Console.WriteLine(" 閉じました "); return; -4-

// 切断されたか調べる if (len <= 0) System.Console.WriteLine(" 切断されました "); so.socket.close(); return; // 受信したデータを蓄積する so.receiveddata.write(so.receivebuffer, 0, len); if (so.socket.available == 0) // 最後迄受信した時 受信したデータを文字列に変換 string str = System.Text.Encoding.UTF8.GetString( so.receiveddata.toarray()); // 受信した文字列を表示 System.Console.WriteLine(str); so.receiveddata.close(); so.receiveddata = new System.IO.MemoryStream(); // 再び受信開始 so.socket.beginreceive(so.receivebuffer, 0, so.receivebuffer.length, System.Net.Sockets.SocketFlags.None, new System.AsyncCallback(ReceiveDataCallback), so); 此処で注意しなければ成らないのが コールバックメソッドは 初めに BeginReceive を呼び出したスレッドとは別のスレッドで実行されると謂う事で有る 詰り スレッドの同期が必要に成るケースが充分有り得る 例えば Socket クラスはスレッドセーフではないので 上記の様な非同期受信を行い乍 Send メソッド等を呼び出す場合には lock(vb.net では SyncLock) 等を使用してスレッドの同期を行う必要が有ると謂う事に成る ( 実際に此の様にして居るサンプルは殆ど見ないが ) 亦 受信したデータをテキストボックスに表示する場合等 コールバックメソッドからコントロールのメソッドを呼び出す時は Invoke メソッド ( 又は BeginInvoke メソッド ) を使用してコントロールのスレッドにマーシャリングする Socket クラスにはデータの受信以外に リモートホストへの接続 (BeginConnect EndConnect メソッド ) データの送信 (BeginSend EndSend メソッド ) の為の非同期メソッドも用意されて居る サーバーの作成 サーバーでは Socket.Bind メソッドでバインドし Listen メソッドでクライアントの接続を待機し Accept メソッドで接続を受け入れると謂うのが基本的な流れで有る 併し Accept メソッドは接続要 -5-

求がない限りブロックし続けて了う 此の対処法としては 先程と同様に ポーリング ( 参照資料 3) 非同期メソッド ( 参照資料 2) 更に スレッド化 ( 参照資料 1) と謂った方法が考えられる ポーリングでは 先と同じく Poll メソッドで接続の要求がないかループで監視し 有れば Accept メソッドで受け入れる様にする スレッド化に依る方法では Accept メソッドの呼び出しを別のスレッドで行う様にする ( 此の方法では接続の待機を中止する為に スレッドセーフでない Socket クラスの Close メソッドを別のスレッドから呼び出す事に成る ) DOBON Chat では 非同期メソッドの BeginAccept EndAccept メソッドを使用して居る 以下に BeginAccept メソッドを使った簡単な例を示す Listen メソッドが既に呼び出されて居る Socket を此の StartAccept メソッドに渡す事に依り クライアントからの接続を非同期で待機する VB ' クライアントの接続待ちスタート Private Shared Sub StartAccept(ByVal server As System.Net.Sockets.Socket) ' 接続要求待機を開始する server.beginaccept(new System.AsyncCallback(AddressOf AcceptCallback), server) End Sub ' BeginAccept のコールバック Private Shared Sub AcceptCallback(ByVal ar As System.IAsyncResult) ' サーバー Socket の取得 Dim server As System.Net.Sockets.Socket = CType(ar.AsyncState, System.Net.Sockets.Socket) ' 接続要求を受け入れる Dim client As System.Net.Sockets.Socket = Nothing Try ' クライアント Socket の取得 client = server.endaccept(ar) Catch System.Console.WriteLine(" 閉じました ") Return End Try ' クライアントが接続した時の処理を此処に書く ' 此処では文字列を送信して 直ぐに閉じて居る client.send(system.text.encoding.utf8.getbytes(" こんにちは ")) client.shutdown(system.net.sockets.socketshutdown.both) client.close() ' 接続要求待機を再開する server.beginaccept(new System.AsyncCallback(AddressOf AcceptCallback), server) End Sub C# // クライアントの接続待ちスタート private static void StartAccept(System.Net.Sockets.Socket server) -6-

// 接続要求待機を開始する server.beginaccept(new System.AsyncCallback(AcceptCallback), server); // BeginAccept のコールバック private static void AcceptCallback(System.IAsyncResult ar) // サーバー Socket の取得 System.Net.Sockets.Socket server = (System.Net.Sockets.Socket) ar.asyncstate; // 接続要求を受け入れる System.Net.Sockets.Socket client = null; try // クライアント Socket の取得 client = server.endaccept(ar); catch System.Console.WriteLine(" 閉じました "); return; // クライアントが接続した時の処理を此処に書く // 此処では文字列を送信して 直ぐに閉じて居る client.send(system.text.encoding.utf8.getbytes(" こんにちは ")); client.shutdown(system.net.sockets.socketshutdown.both); client.close(); // 接続要求待機を再開する server.beginaccept( new System.AsyncCallback(AcceptCallback), server); EndAccept メソッドに依り 接続したクライアントとの通信に使用する Socket オブジェクトが返される 上記のコードでは 接続したクライアントに文字列を UTF-8 でエンコードしたデータを送信し 直ぐに接続を閉じて居る チャットアプリケーションのサーバーでは 或るクライアントから受信したメッセージを接続中の総てのクライアントに送信する必要が有る 此れは単純に クライアントからデータを受信したら 接続中の一つ一つのクライアントの Socket.Send( 又は BeginSend) メソッドを呼び出してデータを送信する様にすれば良い 独自のアプリケーションプロトコルの定義 以上で チャットアプリケーションを作成する為の知識が揃いました 此れで当初の目的には達したと謂って良い -7-

併し 文字列の遣り取りが出来る様に成ったとは謂え 此れ丈では実用的なチャットアプリケーションには程遠い 現状では クライアント側で現在チャットに参加して居るメンバーを表示する事も 送られて来たメッセージを表示する時に其の送信者を併記する事も出来ないので有る 更に プライベートメッセージ ( 指定した人にしかメッセージを送信しない ) 等の機能は何の様に実装すれば良いのか 此の様に様々な機能を持つチャットアプリケーションを作成する為には 予めサーバーとクライアントの間で機能に応じた 決まり を用意して置く必要が有る 此れは アプリケーション層プロトコルと呼ばれる物で有る 此の 決まり は極簡単な物で構わない ( ちゃんとした物を作るならば RFC 特にチャットアプリケーションでは IRC が参考に成るだろう ) 良く有る 決まり の形式は 文字列のコマンドと一つ以上のパラメータから成り 夫々をスペース文字で区切り CR-LF( キャリッジリターン + ラインフィード ) で終わると謂う物で有る 例えば クライアントがプライベートメッセージを送信する時は PRIVMSG " メッセージの送信先 " " メッセージの内容 "CR-LF と謂う内容の文字列を UTF-8 でエンコードしたデータを送信すると決めて置く 此の様にして置く事に依り サーバーは PRIVMSG で始まり CR-LF で終わる文字列を受信した時に 其れがクライアントがプライベートメッセージの送信を要求して居る合図で有ると解り メッセージの内容と送信先を正しく理解する事が出来る 同様に サーバーからクライアントへのプライベートメッセージの送信でも PRIVMSG " メッセージの送信者 " " メッセージの内容 "CR-LF と謂う決まりにして置けば クライアントが PRIVMSG で始めるデータを受信した時 其のデータが自分丈に送られて来たプライベートメッセージで有り 誰が何の様なメッセージを送って来たのかが解る 此の様なコマンド ( 上記の例では PRIVMSG ) を増やして行く事に依り 機能を拡張する事が出来る 纏め 此の記事では TCP を利用した複数クライアントが接続可能なチャットアプリケーションの作り方を説明した ポイントを纏めると次の様に成る チャットアプリケーションでは長時間ブロックするメソッドの使用は厳禁で有る為 ( 例外有り ) 非同期メソッドの活用が有効で有る 非同期メソッドに依り呼び出されるコールバックメソッドは個別のスレッドで実行される為 スレッドの同期等の対策が必要と成る 既存のアプリケーション層プロトコルを利用しないならば 独自のアプリケーション層プロトコルを定義しなければ成らない -8-

参考資料 1.MSDN ライブラリ Creating a Multi-User TCP Chat Application 2.CodeGuru Asynchronous Socket Programming in C# 3.CSharpFriends.com Non-blocking Sockets (A Chat Program) 4.MSDN ライブラリ 非同期クライアントソケットの使用 5.MSDN ライブラリ 非同期サーバーソケットの使用 6.MSDN ライブラリ 非同期クライアントソケットの例 7.MSDN ライブラリ 非同期サーバーソケットの例 http://codezine.jp/article/detail/22-9-

Socket を使って HTTP でファイルをダウンロードし表示する Socket クラスを使って HTTP サーバーに GET 要求し 応答を受信する方法を 具体例而巳示す 通常は WebRequest WebResponse クラスを使ってファイルをダウンロードし表示する の様な方法で充分で有る 説明は一切しないので 興味のある方而巳参考にして欲しい VB ' GET リクエストを送信するサーバー名とパス Dim server As String = "www.google.co.jp" Dim path As String = "/" ' リクエストメッセージを作成する Dim reqmsg As String = "GET " + path + " HTTP/1.1" + vbcrlf + _ "Host: " + server + vbcrlf + "Connection: Close" + vbcrlf + vbcrlf ' 文字列を byte 配列に変換 Dim enc As System.Text.Encoding = System.Text.Encoding.GetEncoding("shift_jis") Dim reqbytes As Byte() = enc.getbytes(reqmsg) ' ホスト名から IP アドレスを取得 Dim hostadd As System.Net.IPAddress = System.Net.Dns.Resolve(server).AddressList(0) ' 又は ' System.Net.IPAddress hostadd = System.Net.Dns.GetHostByName(server).AddressList(0) ' IPEndPoint を取得 Dim ephost As New System.Net.IPEndPoint(hostadd, 80) ' Socket の作成 Dim sock As New System.Net.Sockets.Socket( _ System.Net.Sockets.AddressFamily.InterNetwork, _ System.Net.Sockets.SocketType.Stream, _ System.Net.Sockets.ProtocolType.Tcp) ' 接続 sock.connect(ephost) ' リクエストメッセージを送信 sock.send(reqbytes, reqbytes.length, System.Net.Sockets.SocketFlags.None) ' 受信する Dim resbytes(1023) As Byte Dim mem As New System.IO.MemoryStream While True Dim ressize As Integer = _ sock.receive(resbytes, resbytes.length, System.Net.Sockets.SocketFlags.None) If ressize = 0 Then Exit While End If -10-

mem.write(resbytes, 0, ressize) End While Dim resmsg As String = enc.getstring(mem.getbuffer(), 0, CInt(mem.Length)) mem.close() ' 閉じる sock.shutdown(system.net.sockets.socketshutdown.both) sock.close() ' 受信したメッセージを表示する Console.WriteLine(resMsg) C# // GET リクエストを送信するサーバー名とパス string server = "www.google.co.jp"; string path = "/"; // リクエストメッセージを作成する string reqmsg = "GET " + path + " HTTP/1.1 r n" + "Host: " + server + " r n" + "Connection: Close r n r n"; // 文字列を byte 配列に変換 System.Text.Encoding enc System.Text.Encoding.GetEncoding("shift_jis"); byte [] reqbytes = enc.getbytes(reqmsg); // ホスト名から IP アドレスを取得 System.Net.IPAddress hostadd = System.Net.Dns.Resolve(server).AddressList[0]; // 又は // System.Net.IPAddress hostadd = System.Net.Dns.GetHostByName(server).AddressList[0]; // IPEndPoint を取得 System.Net.IPEndPoint ephost = new System.Net.IPEndPoint(hostadd, 80); // Socket の作成 System.Net.Sockets.Socket sock = new System.Net.Sockets.Socket( System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); // 接続 sock.connect(ephost); // リクエストメッセージを送信 sock.send(reqbytes, reqbytes.length, System.Net.Sockets.SocketFlags.None); // 受信する -11-

byte [] resbytes = new byte[1024]; System.IO.MemoryStream mem = new System.IO.MemoryStream(); while (true) int ressize = sock.receive(resbytes, resbytes.length, System.Net.Sockets.SocketFlags.None); if (ressize == 0) break; mem.write(resbytes, 0, ressize); string resmsg = enc.getstring(mem.getbuffer(), 0, (int) mem.length); mem.close(); // 閉じる sock.shutdown(system.net.sockets.socketshutdown.both); sock.close(); // 受信したメッセージを表示する Console.WriteLine(resMsg); -12-