回答編集履歴

7

変数の型をvarにTask.Factory.StartNewを追加

2018/04/10 06:48

投稿

umyu
umyu

スコア5846

test CHANGED
@@ -60,9 +60,19 @@
60
60
 
61
61
  public void OnRequested(IAsyncResult res){
62
62
 
63
- HttpListener listener = (HttpListener)res.AsyncState;
63
+ var listener = res.AsyncState as HttpListener;
64
64
 
65
+ if (!listener.IsListening)
66
+
67
+ {
68
+
69
+ // 受信開始→終了でOnRequestedイベントが発火するため、受信待機状態でない時はSkip
70
+
71
+ return;
72
+
73
+ }
74
+
65
- HttpListenerContext context = listener.EndGetContext(res);
75
+ var context = listener.EndGetContext(res);
66
76
 
67
77
 
68
78
 
@@ -140,21 +150,25 @@
140
150
 
141
151
  public void OnRequested(IAsyncResult res){
142
152
 
143
- TcpListener listener = res.AsyncState as TcpListener;
153
+ var listener = res.AsyncState as TcpListener;
144
154
 
145
- TcpClient client = listener.EndAcceptTcpClient(res);
155
+ var client = listener.EndAcceptTcpClient(res);
146
156
 
147
157
 
148
158
 
149
159
  listener.BeginAcceptTcpClient(this.OnRequested, listener);
150
160
 
151
-   // これ以下は各クライアントでやりたいこと。async/awaitなどの並列化処理を使ってください。
161
+ Task.Factory.StartNew(() =>
152
162
 
153
- client.Client.RemoteEndPoint;
163
+ {
154
164
 
155
- NetworkStream stream = client.GetStream();
165
+    //これ以降は各クライアントで行いたい処理。
156
166
 
167
+ client.Client.RemoteEndPoint;
157
168
 
169
+ var stream = client.GetStream();
170
+
171
+ });
158
172
 
159
173
  }
160
174
 

6

追記

2018/04/10 06:48

投稿

umyu
umyu

スコア5846

test CHANGED
@@ -148,7 +148,7 @@
148
148
 
149
149
  listener.BeginAcceptTcpClient(this.OnRequested, listener);
150
150
 
151
-   // これ以下は各クライアントでやりたいこと。
151
+   // これ以下は各クライアントでやりたいこと。async/awaitなどの並列化処理を使ってください。
152
152
 
153
153
  client.Client.RemoteEndPoint;
154
154
 

5

追記

2018/04/10 06:18

投稿

umyu
umyu

スコア5846

test CHANGED
@@ -142,7 +142,7 @@
142
142
 
143
143
  TcpListener listener = res.AsyncState as TcpListener;
144
144
 
145
- TcpClient context = listener.EndAcceptTcpClient(res);
145
+ TcpClient client = listener.EndAcceptTcpClient(res);
146
146
 
147
147
 
148
148
 
@@ -150,7 +150,9 @@
150
150
 
151
151
    // これ以下は各クライアントでやりたいこと。
152
152
 
153
+ client.Client.RemoteEndPoint;
154
+
153
-   // context にはクライアントのIPアドレスとStreamがあるはずです。
155
+ NetworkStream stream = client.GetStream();
154
156
 
155
157
 
156
158
 

4

追記

2018/04/10 05:49

投稿

umyu
umyu

スコア5846

test CHANGED
@@ -85,3 +85,75 @@
85
85
  0. [TcpListener#BeginAcceptTcpClient](https://msdn.microsoft.com/ja-jp/library/system.net.sockets.tcplistener.beginaccepttcpclient(v=vs.110).aspx)
86
86
 
87
87
  1. [HttpListener クラス](https://msdn.microsoft.com/ja-jp/library/system.net.httplistener(v=vs.110).aspx)
88
+
89
+
90
+
91
+ ---
92
+
93
+
94
+
95
+ コンパイル通してませんが、TcpListener の場合はこのような形です。
96
+
97
+ ```C#
98
+
99
+ private TcpListener server = new TcpListener();
100
+
101
+ private readonly object locker = new object();
102
+
103
+ public Action<string> OnLogWrite;// ログ出力用
104
+
105
+ public void Start()
106
+
107
+ {
108
+
109
+ lock (this.locker)
110
+
111
+ {
112
+
113
+ // ここらへんでlistenとbindが必要なはず。
114
+
115
+ // start
116
+
117
+ this.server.Start();
118
+
119
+ this.server.BeginAcceptTcpClient(this.OnRequested, this.server);
120
+
121
+ }
122
+
123
+ }
124
+
125
+ public void Stop()
126
+
127
+ {
128
+
129
+ lock (this.locker)
130
+
131
+ {
132
+
133
+ this.server.Close();
134
+
135
+ this.server = new TcpListener();
136
+
137
+ }
138
+
139
+ }
140
+
141
+ public void OnRequested(IAsyncResult res){
142
+
143
+ TcpListener listener = res.AsyncState as TcpListener;
144
+
145
+ TcpClient context = listener.EndAcceptTcpClient(res);
146
+
147
+
148
+
149
+ listener.BeginAcceptTcpClient(this.OnRequested, listener);
150
+
151
+   // これ以下は各クライアントでやりたいこと。
152
+
153
+   // context にはクライアントのIPアドレスとStreamがあるはずです。
154
+
155
+
156
+
157
+ }
158
+
159
+ ```

3

追記

2018/04/10 05:22

投稿

umyu
umyu

スコア5846

test CHANGED
@@ -1,8 +1,10 @@
1
- 大前提
1
+ ベストカレントプラティクス
2
2
 
3
- 今なら、`WebSocket`で作た方が楽に作れような気ます
3
+ `WebSocket`で作成される一番だと思います。
4
4
 
5
5
 
6
+
7
+ ◇以下は処理案です。
6
8
 
7
9
  1,あまりコードをよく見ていませんが、`server.AcceptTcpClient`の戻り値をスレッドプールで処理するのも一つの手ですが、クライアントのメッセージを受信部分は非同期処理の`server.BeginAcceptTcpClient`を使うのも一つの手かと。
8
10
 

2

tcplistenerにはBeginGetContextがなかったので訂正

2018/04/10 03:25

投稿

umyu
umyu

スコア5846

test CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
 
6
6
 
7
- 1,あまりコードをよく見ていませんが、`server.AcceptTcpClient`の戻り値をスレッドプールで処理するのも一つの手ですが、クライアントのメッセージを受信部分は`server.BeginGetContext`を使うのも一つの手かと。
7
+ 1,あまりコードをよく見ていませんが、`server.AcceptTcpClient`の戻り値をスレッドプールで処理するのも一つの手ですが、クライアントのメッセージを受信部分は非同期処理の`server.BeginAcceptTcpClient`を使うのも一つの手かと。
8
8
 
9
9
  2,`RunRecvMessageAsync`内で、 `server = new TcpListener(localAddr, PortnumSV);`を行うのではなく。`StartServer`と`StopSever`で行ってください。
10
10
 
@@ -12,7 +12,7 @@
12
12
 
13
13
  3,`TcpListener`を使っても最終的には独自の通信プロトコルを作成する必要があるため、`TcpListener`ではなく`HttpListener`を使うと、プロトコルのデバック作業が楽になります。
14
14
 
15
- 動作確認してませんが、こんな感じです
15
+ 動作確認してませんが、サンプルソースです雰囲気を感じ取ってくださいな
16
16
 
17
17
  ```C#
18
18
 
@@ -72,6 +72,14 @@
72
72
 
73
73
  ```
74
74
 
75
- 4.変数:`status`をクライアントの接続の度に変更しているのも複数接続で、破綻しているのではないでしょうか。
75
+ 4.`RunRecvMessageAsync`メソッド内で、変数:`status`をクライアントの接続の度に変更しているのも複数接続で、破綻しているのではないでしょうか。
76
76
 
77
77
  5,画面やログの書き出しは`action`を定義すると便利です。スレッドセーフを意識してくださいな。
78
+
79
+
80
+
81
+ ◇参考情報
82
+
83
+ 0. [TcpListener#BeginAcceptTcpClient](https://msdn.microsoft.com/ja-jp/library/system.net.sockets.tcplistener.beginaccepttcpclient(v=vs.110).aspx)
84
+
85
+ 1. [HttpListener クラス](https://msdn.microsoft.com/ja-jp/library/system.net.httplistener(v=vs.110).aspx)

1

追記

2018/04/10 03:04

投稿

umyu
umyu

スコア5846

test CHANGED
@@ -1,24 +1,18 @@
1
+ ◇大前提
2
+
1
- 今なら、WebSocketで作られた方が楽に作れるような気がしますが。
3
+ 今なら、`WebSocket`で作られた方が楽に作れるような気がしますが。
2
4
 
3
5
 
4
6
 
5
- 1,あまりコードをよく見ていませんが、server.AcceptTcpClientの戻り値をスレッドプールで処理するのも一つの手ですが、クライアントのメッセージを受信部分はserver.BeginGetContextを使うのも一つの手かと。
7
+ 1,あまりコードをよく見ていませんが、`server.AcceptTcpClient`の戻り値をスレッドプールで処理するのも一つの手ですが、クライアントのメッセージを受信部分は`server.BeginGetContext`を使うのも一つの手かと。
6
8
 
7
- 2,RunRecvMessageAsync内で、 server = new TcpListener(localAddr, PortnumSV);を行うのではなく。StartServerとStopSeverで行ってください。
9
+ 2,`RunRecvMessageAsync`内で、 `server = new TcpListener(localAddr, PortnumSV);`を行うのではなく。`StartServer``StopSever`で行ってください。
8
10
 
9
11
 
10
12
 
11
- 3,TcpListenerを使っても最終的には独自の通信プロトコルを作成する必要があるため、TcpListenerではなくHttpListenerを使うと、プロトコルのデバック作業が楽になります。
13
+ 3,`TcpListener`を使っても最終的には独自の通信プロトコルを作成する必要があるため、`TcpListener`ではなく`HttpListener`を使うと、プロトコルのデバック作業が楽になります。
12
14
 
13
15
  動作確認してませんが、こんな感じです。
14
-
15
-
16
-
17
- 4.変数:statusをクライアントの接続の度に変更しているのも複数接続で、破綻するのではないかと少し気になってます。
18
-
19
- 5,画面やログの書き出しはactionを定義すると便利です。
20
-
21
-
22
16
 
23
17
  ```C#
24
18
 
@@ -77,3 +71,7 @@
77
71
  }
78
72
 
79
73
  ```
74
+
75
+ 4.変数:`status`をクライアントの接続の度に変更しているのも複数接続で、破綻しているのではないでしょうか。
76
+
77
+ 5,画面やログの書き出しは`action`を定義すると便利です。スレッドセーフを意識してくださいな。