今回は、WinSockである程度まとまったデータをネットワークで送る際のパフォーマンスや処理方式を検討するために、現在のディスプレイの画像を送受信してみます。最近の画面解像度はXGA(1024*768)あたりが最低線で、これをフルカラー(1ピクセル3バイト)で送るとなるとデータ量は3MB程度にはなるでしょう。このくらいのデータ量なら、データの送受信にも、ある程度の時間がかかるはずです。そこで、送受信のパラメータをいろいろ変えてみてデータ転送の効率がどうなるのか、試してみることにしました。今回は、画像を送信する側と受信する側2つのプログラムを作成します。最初に送信側のプログラムを作ってみましょう。送信プログラムは、単に画像を生成・送信するだけなのでコマンドラインで動くプログラムにしてみました。画像データを送信するには、最初に送信する画像データを作らないといけませんね。今回は現在のディスプレイを画像として送信するので、ディスプレイのデバイスコンテキストを取得し、それを24ビットDIBSectionに描画して24ビットDIBピクセル列を取得することにしました。SRCCOPY);これでDIBSectionのピクセル列lpPixelsに画面の画像データが得られました。画像データができたら、これを送信します。今回は、通信のプロトコルを以下のように定めました。データ受信側(サーバー)は、ポート7000番で送信側(クライアント)からの接続を待つ。クライアントは、サーバーに接続したらまず画像サイズを縦横各4バイト、計8バイトで送る。サーバーは取得した画像サイズを元に受信準備を行い、1バイトの応答を返す。クライアントはサーバーの応答を待って、実際の画像データを送信する。送信が終わったら、ソケットを閉じる。このプロトコルでは、途中のエラーは一切考慮しません。送信側で行う処理は、受信側に接続して8バイトの画像サイズを送り、受信側からの応答を待つ。応答があったら、あとは画像のピクセル列をそのまま送信して接続を切る、という流れになります。3;となります(通常画面の横幅は4の倍数ピクセルなので、今回は4バイト境界は考慮しません)。バッファサイズが求まったら、実際にバッファを確保しデータを書き込んでおきましょう。3);これで送信するデータができたので、実際にサーバーと通信を開始します。通信ソケットの作成は、サーバーのアドレス(lpszAddr)とポート(wPort)を元に以下のようにします。sizeof(saConnect);通信に使うソケットができたら、最初にバッファの先頭8バイト(画像サイズ)を送信し、サーバーから来るはずの1バイトの応答を待ちます。1);サーバーから応答があったら、あとはバッファの内容をすべて送信するだけです。送信時には、send()の引数に送信サイズを指定するので、今回はその数値(iLineSize)に最大iSendSizeを指定するようにしました。送信ループでは、送信量がバッファサイズに達するまで、send()を繰り返します。できたので、次は受信側です。受信側は、受信した画像を表示するので画像表示用のウインドウを持つWindowsアプリにしました。最初に受信用のスレッドを作成し、そのスレッドでクライアントからの通信を待ち、受信処理を行います。通信スレッド関数threadfunc()では、最初にポート7000番に待機用のソケットを作成して接続されるのを待ちます。&iLen);ソケットsConnectで接続を確立したら、最初に画像サイズの8バイトを受信して画像データ用バッファを確保します。iSize);画像データを受信するバッファを確保したら、クライアントに応答し、実際に画像データを受信。受信時のrecv()でも受信サイズを指定するので、そのサイズを最大iGetSizeバイトになるよう調整します。}データを受信したら、ソケットを閉じて受信した画像データ用の24ビットDIBヘッダを作成します。画像表示フラグをセットし、画面に画像を表示。UpdateWindow(hwMain);これで、クライアントでのデータ作成・送信とサーバーでのデータ受信・画像表示という一連の流れができました。送受信実験では、実際にサーバー・クライアントプログラムを使って画像の送受信実験を行ってみましょう。今回、送受信の効率に影響しそうなのはsend()/recv()で指定する送受信のデータ単位サイズ(iSendSize/iGetSize)です。そこで、この2つの大きさをいろいろ変えて画像を送受信してみることにしました。XP/1152*864ピクセル)で試してみたところ、経過時間の値が正の値にならずクライアント側の測定ができないことが多いです(^^;。大体、測定できる時はクライアント側が600-800Mbps、サーバー側が60Mbps程度になるようですね(といっても、測定できないこともあるのでこの数値の精度にも問題がある気がしますが)。Me/1024*768ピクセル)にクライアントを入れて、メインマシンのサーバーと通信し、ネットワーク経由(LAN)の通信時間を測定してみました。その結果が以下の表です。表は、横軸がクライアント側のiSendSize、縦軸がサーバー側のiGetSizeです。測定データは、上がクライアント、下がサーバー側の送受信処理時間(ビットレート)という形になっています。5.5.1でビルドした物を使用しました。291(64.9Mbps)318(59.3Mbps)なんか、あまり差がないですね。このあたりの値は、あまり極端な設定をしなければ大差がないのでしょうか。"127.0.0.1";を環境に合わせて書き換えてください。クライアントとサーバー両方のプログラムをビルドしたら、まずサーバーを起動します。続いてクライアントを起動すると、クライアントプログラムが動いているマシンのデスクトップ画像がサーバープログラムに送られ表示されます。結果を確認したら、両方のプログラムを終了しましょう(一度送信したら、必ずサーバーも終了してください)。