クラス構成図
using System; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using Util; namespace WifiModule { public class Wifi { public delegate void Delegate(string message); Delegate callback; IPAddress remoteIpAddress; Socket remoteSocket; volatile bool threadRunFlg = false; readonly object lockObject = new object();
コンストラクタ
String ipAddress IPアドレス
Delegate function ファンクション
なし
・初期処理
・コールバック登録
// コンストラクタ
public Wifi(string ipAddress, Delegate function) {
remoteIpAddress = IPAddress.Parse(ipAddress);
callback = function;
}
TCP接続する
なし
Boolean処理結果
・指定したアドレスファミリ(AddressFamily.InterNetwork)、ソケットタイプ(SocketType.Stream)、プロトコルタイプ(ProtocolType.Tcp)を使用してSocketクラスのインスタンスを初期化
・指定したIPアドレスとポート番号(Archでは9005固定)を使用してソケット通信接続
// TCP接続
public bool Connect() {
bool isConnect = false;
remoteSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
remoteSocket.Connect(remoteIpAddress, 9005); // 接続に失敗した場合(2重接続等)、エラー発生
if (remoteSocket.Connected) {
threadRunFlg = true;
new Thread(ReceiveMsg).Start();
isConnect = true;
}
return isConnect;
}
TCP切断する
なし
なし
・ソケット通信切断
// TCP切断
public void DisConnect() {
threadRunFlg = false;
lock (lockObject) {
if (remoteSocket != null) {
remoteSocket.Shutdown(SocketShutdown.Both);
remoteSocket.Close();
remoteSocket = null;
}
}
}
要求電文を送信する
string msg 要求電文
※各サービスの要求電文の設定内容については接続仕様書参照
int 処理結果(0:正常、1:エラー)
・Base64エンコード処理呼び出し
・JIS-8単位符号化処理呼び出し
・TLV形式変換処理呼び出し
・ブロック分割(32KB)
・TCP送信処理呼び出し
// 電文送信 public int SendMsg(string msg) { lock (lockObject) { // ソケットが接続されていれば電文を送信する。 if (remoteSocket != null && remoteSocket.Connected) { if (!string.IsNullOrEmpty(msg)) { // 引数がnullもしくは""でなければ送信 // Base64エンコード msg = Utility.EncodeBase64(msg); // JIS-8単位符号化 byte[] msgArray = Utility.EncodeJis8(msg); // TLV形式に変換 string tlvString = Utility.CreateMassageTLV(msgArray); // 32KBで分割して送信 int stringSize = 2 * 32 * 1024; // 最大送信データサイズ:1バイト当り2文字×32KB int subStringIndex = 0; while (subStringIndex < tlvString.Length) { // 未送信の電文が残っている場合 string tempStr; if (tlvString.Substring(subStringIndex).Length > stringSize) { // 残りの電文内容の文字数が最大送信データサイズより大きい場合 // 残りの文字列から最大送信データサイズ分だけ取り出す tempStr = tlvString.Substring(subStringIndex, stringSize); } else { // 残りの電文内容の文字数が最大送信データサイズに収まる場合 // 残りの文字列を取り出す tempStr = tlvString.Substring(subStringIndex); } // 電文送信 byte[] sendDataByte = Utility.HexToByte(tempStr); SendData(sendDataByte, 0, sendDataByte.Length); // 未送信の電文の開始位置の更新 subStringIndex += tempStr.Length; } return 0; } else { // 引数がnullもしくは""であれば1(エラー)を返却 return 1; } } else { // ソケットが接続されてなければ1(エラー)を返却 return 1; } } }
TCP送信する
byte[] data 送信電文
int i 開始位置
int length バイト数
なし
・TCP送信
// TCP送信
void SendData(byte[] data, int i, int length) {
remoteSocket.Send(data, i, length, SocketFlags.None);
}
応答電文を受信する
なし
なし
・TCP受信
・32KB分割を結合
・TLV形式を解析
・JIS-8単位符号復号化
・Base64デコード
・コールバック処理
// 電文受信 void ReceiveMsg() { byte[] buffer = new byte[32 * 1024]; // 受信データサイズ(32KB) StringBuilder receiveDataBuffer = new StringBuilder(); StringBuilder receiveDataLengthBuffer = new StringBuilder(); bool receiveFlg = false; while (threadRunFlg) { int byteSize = -1; try { // 受信を待機 byteSize = remoteSocket.Receive(buffer); } catch (Exception) { break; } if (byteSize > 0) { string outmsg = ""; // 受信データを読み込む string readDataStr = Utility.ToHexString(buffer, byteSize); // 受信データの識別子をチェックする if (readDataStr.Substring(0, 2) == "ff") { receiveDataLengthBuffer.Clear(); receiveDataBuffer.Clear(); readDataStr = readDataStr.Substring(2); receiveFlg = true; } // 受信データのデータ部レングスをチェックする if (receiveFlg) { for (int i = 0; i < readDataStr.Length; i++) { if (receiveDataLengthBuffer.Length < 8) { // 受信データのデータ部レングスが8バイトになるまで、データ部レングスバッファに1バイトずつ積込む receiveDataLengthBuffer.Append(readDataStr[i]); } else { // データ部レングスが8バイトに満たした場合、残りのデータをデータ部バッファに積込む receiveDataBuffer.Append(readDataStr[i]); } } } // 受信データのデータ部をチェックする if (receiveDataBuffer.Length == int.Parse(receiveDataLengthBuffer.ToString())) { receiveFlg = false; byte[] msgArray = Utility.HexToByte(receiveDataBuffer.ToString()); // JIS-8単位符号復号化 string msg = Utility.DecodeJis8(msgArray); // Base64デコード outmsg = Utility.DecodeBase64(msg); // 電文を返却 callback(outmsg); } } else { break; } } } } }
Base64エンコードする
string msg 変換前文字列
string 変換後文字列
・Base64エンコード(76 文字ごとに改行を挿入)
namespace Util {
public static class Utility {
// Base64エンコード
public static string EncodeBase64(string msg) {
return Convert.ToBase64String(Encoding.UTF8.GetBytes(msg), Base64FormattingOptions.InsertLineBreaks);
}
Base64デコードする
string msg 変換前文字列
string 変換後文字列
・Base64デコード
// Base64デコード
public static string DecodeBase64(string msg) {
return Encoding.UTF8.GetString(Convert.FromBase64String(msg));
}
JIS-8単位符号化する
string msg 変換前文字列
byte[] 変換後バイト型配列
・JIS-8単位符号化
// JIS8単位符号化
public static byte[] EncodeJis8(string msg) {
return Encoding.UTF8.GetBytes(msg);
}
JIS-8単位符号復号化する
byte[] msgArray 変換前バイト型配列
string msg 変換後文字列
・JIS-8単位符号復号化
// JIS8単位符号復号化
public static string DecodeJis8(byte[] msgArray) {
return Encoding.UTF8.GetString(msgArray);
}
16進数復元処理を行う
string hexStr 変換前文字列
byte[] 変換後バイト型配列
・16進数復元処理
// 16進数復元処理
public static byte[] HexToByte(string hexStr) {
int strLength = hexStr.Length / 2;
byte[] bytes = new byte[strLength];
int j = 0;
for (int i = 0; i < strLength; i++) {
bytes[i] = Convert.ToByte(hexStr.Substring(j, 2), 16);
j += 2;
}
return bytes;
}
16進文字列変換処理を行う
byte[] bytes 変換前バイト型配列
int size 変換前バイト型配列の長さ
string 変換後文字列
・16進文字列変換処理
// 16進文字列変換処理
public static string ToHexString(byte[] bytes, int size) {
StringBuilder sb = new StringBuilder(size * 2);
for (int i = 0; i < size; i++) {
if (bytes[i] < 16) {
sb.Append('0');
}
sb.Append(Convert.ToString(bytes[i], 16));
}
return sb.ToString();
}
送信電文(TLV形式)の作成を行う
byte[] msgArray 変換前バイト型配列
string 変化後文字列
・TLV形式変換処理
// TLV形式変換
public static string CreateMassageTLV(byte[] msgArray) {
StringBuilder sendDataSb = new StringBuilder();
string hexStr = BitConverter.ToString(msgArray);
hexStr = hexStr.Replace("-", "");
sendDataSb.Append("ff");
sendDataSb.Append(string.Format("{0:00000000}", hexStr.Length));
sendDataSb.Append(hexStr);
return sendDataSb.ToString();
}
}
}
コードをコピーしました