非同期ソケットを使い、対象機器と通信を行うアプリケーションの作成をしています。
対象機器はパソコン等ではありません
実際に作成して、最低限の欲しい動作は確保できたのですが
細かい部分などを実現させようとすると、コードが汚くなってしまいそうだなと思い
拡張性を保てるように、全体のコードを見直そうかなと考えています
考え方の参考のために皆様の意見や知識を貰いたいと思い質問させていただきます。
.NET Frameworkのバージョンは4.5.2です
C#
1 public MainForm() 2 { 3 // 受信タスクの非同期実行. 4 var task = Task.Run(() => 5 { 6 StartListening(); 7 }); 8 } 9 10 public void StartListening() 11 { 12 m_Accept.Reset(); 13 m_Accept.WaitOne(); 14 15 try 16 { 17 while (true) 18 { 19 m_Accept.Reset(); 20 21 m_Listener.BeginAccept(new AsyncCallback(AcceptCallback), m_Listener); 22 23 m_Accept.WaitOne(); 24 } 25 26 } 27 catch 28 { 29 // 例外処理をどうするか 30 } 31 } 32 33 public void AcceptCallback(IAsyncResult ar) 34 { 35 m_Accept.Set(); 36 37 Socket Listener; 38 Socket Handler; 39 40 try 41 { 42 Listener = (Socket)ar.AsyncState; 43 Handler = Listener.EndAccept(ar); 44 } 45 catch (Exception) 46 { 47 return; 48 } 49 50 StateObject State = new StateObject(); 51 State.workSocket = Handler; 52 53 Handler.BeginReceive(State.buffer, 0, StateObject.buffersize, 0, new AsyncCallback(ReadCallback), State); 54 } 55 56 public void ReadCallback(IAsyncResult ar) 57 { 58 int OldIndex = 0; 59 int BytesRead = 0; 60 61 try 62 { 63 StateObject State = (StateObject)ar.AsyncState; 64 Socket handler = State.workSocket; 65 66 // クライアントソケットからデータを読み取ります。 67 BytesRead = handler.EndReceive(ar); 68 69 // データを受信しているか 70 if (BytesRead > 0) 71 { 72 /* 73 受信処理 74 */ 75 76 // 再び受信待機をする. 77 handler.BeginReceive(State.buffer, 0, StateObject.buffersize, 0, new AsyncCallback(ReadCallback), State); 78 } 79 // リードデータが0の場合切断検知 80 else 81 { 82 /* 83 切断 84 */ 85 } 86 } 87 catch (Exception) 88 { 89 return; 90 } 91 }
通信に関しては非同期ソケットと検索すると沢山出てくる
BeginAccept、BeginReceiveなどを使っています。
アプリ起動と同時にAcceptを行うためのメソッドを別スレッドに任せて
完全に投げっぱなし状態にしています
アプリからUDPのブロードキャストを使って特定のデータを送り
それを受信した対象機器から接続要求が送られてくる仕組みです
データを送る直前に事前に入力してもらっていた、アプリが動いているPCのIPを元に
ソケットのバインドなどを行うようになっています
アプリ側から接続要求は送りません
一度接続したら、明示的に切断の処理を走らせるまで
接続は維持したまま、受信したデータをその都度処理するために
BeginReceviを繰り返し呼び出すようにしています
直したい点は
・接続要求スレッドの投げっぱなしを辞めたい
接続に失敗したり、IPを変更してやり直したりしたいため
無限ループによる投げっぱなしを辞めたいのですが
何をもってして、スレッドの終了とすればいいのか
送られてきた接続要求が全て処理し終えたらスレッド終了でもいいが
いくつ要求が送られてくるかはわからないし、必ず一斉に送られてくるとも限らない
タイムアウトを導入してもいいがどのように実装するか
・できたら受信処理の部分のBeginReceveの繰り返し呼び出すのもやめたい
理想は何かしらのデータが来たらその都度別スレッドを起こして処理をさせたい
C/C++などのselectのようなものが理想
調べたら出来るそうですが、皆様ならどのように作るかなと思いました
・async/awaitを使った非同期のソケットを導入するべき?
非同期ソケットで検索すると9割がたBeginAcceptを使ったものが出てきますが
async/awaitを使ったほうがコードの記述もすっきりするみたいです
async/awaitの方が新しい技術だと思うのでこっちを使って実装するべきなのかどうか
そもそもselectをつかった実装をする場合必然的にasync/awaitを使うことになるのか
自分の中でも聞きたいことがまとまっていなくてふわふわした感じになってしまって
とても申し訳ないのですが
些細なことでも結構です。糞醜いソースだな!などの意見でも結構です
一人で考えることに限界を感じてきたので、何かしら思い当たることがあったら回答していただけるととても嬉しいです。
よろしくお願い致します。

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/07/02 09:11 編集
2018/07/02 09:18
2018/07/03 00:53
2018/07/03 01:18
2018/07/06 01:49