y-matsui::weblog

電子楽器、音楽、コンピュータ、プログラミング、雑感。面倒くさいオヤジの独り言

Socketクラスを使ったTCP通信関連

Webからソケット通信で既存c++アプリにコマンドを引き渡すc#コンソールプログラムの作成。

■サーバ/クライアント
非同期通信の方法が良く分かるサンプルプロジェクトと記事。

DOBON.NET > プログラミング道 > .NET Tips > インターネット編メニュー
TCPを利用した複数クライアント接続可能なチャットアプリケーションの作成
SocketクラスによるTCP非同期通信の方法

■バイト配列関連
構造体の値をバイト配列に加工してソケットに流すとか、流れてきたバイト配列を復元するとか。.NETのエンコーディングであるUTF-8から、shift-jisに変換するとか。
構造体をバイト配列にするには、BitConverter.GetBytes(数値)、System.Text.Encoding.GetEncoding("shift-jis").GetBytes(文字列)などでバイト配列にしてから、
Buffer.BlockCopy(コピーするバイト配列, 貼り付ける位置, コピー先のバイト配列, 開始位置, バイト数)で送信するバイト配列を作る。これをそのまま、ソケットにWriteして送信してやれば良い・・というのがとりあえずの結論。

アンセーフコードであることを覚悟して(.NETの保護を無視して)memcpyを使うとかの情報もあったが、.NETでmemcpyと同様の動作をするBuffer.BlockCopyを使うのが正しそう。
しかし、Buffer.BlockCopyではポインタをそのまま渡すとか、構造体をざっくりと引き渡すなんていうことが出来ないので、コピー位置を指定して、バイト配列を組み立てるっていうやり方。
固定長のメッセージじゃない場合は、面倒くさいことになりそうだ。

.NET TIPS 文字列をシフトJISとしてバイト列に変換するには?
.NET TIPS バイト列と数値を変換するには?
バイト列を文字列に変換するには?
Top > @IT会議室 > Insider.NET 会議室 > 構造体をbyteにコピーしたい

■構造体
//Socket通信用構造体
public struct SocketStruct
{
  //種別 HEX 2Bytes
  public UInt16 category;
  //コマンド文字列 CHAR(32)
  public string command;
  
  //その他メンバー 
  //......
}

■構造体→バイト配列

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

Encoding enc = System.Text.Encoding.GetEncoding("shift-jis");

byte data;   //バイト配列データ
data=new byte[1024];
byte[] buf;

//数値フィールド HEX 2Bytes
buf = BitConverter.GetBytes(sockcmd.category);
Buffer.BlockCopy(buf, 0, data, 0, 2);

//文字列フィールド CHAR(32)
buf = enc.GetBytes(sockcmd.command);
Buffer.BlockCopy(buf, 0, data, 2, 32);

//その他メンバーを同様に詰め込む
//......


■バイト配列→構造体

//文字列エンコーディング(内部文字コードUTF8をshift-jisに変換するため)
Encoding enc = System.Text.Encoding.GetEncoding("shift-jis");

//構造体
SocketStruct sockcmd = new SocketStruct();

//ここからバイト配列から構造体を組み立てる処理
//種別 HEX 2Bytes
sockcmd.category= BitConverter.ToUInt16(data,0);

//コマンド CHAR(32)
sockcmd.command = enc.GetString(data,2,32);

//その他メンバーを同様に復元する 
//......