teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

7

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

2018/04/10 06:48

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -29,8 +29,13 @@
29
29
  }
30
30
  }
31
31
  public void OnRequested(IAsyncResult res){
32
- HttpListener listener = (HttpListener)res.AsyncState;
32
+ var listener = res.AsyncState as HttpListener;
33
+ if (!listener.IsListening)
34
+ {
35
+ // 受信開始→終了でOnRequestedイベントが発火するため、受信待機状態でない時はSkip
36
+ return;
37
+ }
33
- HttpListenerContext context = listener.EndGetContext(res);
38
+ var context = listener.EndGetContext(res);
34
39
 
35
40
  listener.BeginGetContext(this.OnRequested, listener);
36
41
    // 以下はやりたいこと。
@@ -69,13 +74,15 @@
69
74
  }
70
75
  }
71
76
  public void OnRequested(IAsyncResult res){
72
- TcpListener listener = res.AsyncState as TcpListener;
77
+ var listener = res.AsyncState as TcpListener;
73
- TcpClient client = listener.EndAcceptTcpClient(res);
78
+ var client = listener.EndAcceptTcpClient(res);
74
79
 
75
80
  listener.BeginAcceptTcpClient(this.OnRequested, listener);
81
+ Task.Factory.StartNew(() =>
82
+ {
76
-   // これ以は各クライアントでやりたいこと。async/awaitなどの並列化処理を使ってください
83
+    //これ以は各クライアントで行いたい処理。
77
- client.Client.RemoteEndPoint;
84
+ client.Client.RemoteEndPoint;
78
- NetworkStream stream = client.GetStream();
85
+ var stream = client.GetStream();
79
-
86
+ });
80
87
  }
81
88
  ```

6

追記

2018/04/10 06:48

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -73,7 +73,7 @@
73
73
  TcpClient client = listener.EndAcceptTcpClient(res);
74
74
 
75
75
  listener.BeginAcceptTcpClient(this.OnRequested, listener);
76
-   // これ以下は各クライアントでやりたいこと。
76
+   // これ以下は各クライアントでやりたいこと。async/awaitなどの並列化処理を使ってください。
77
77
  client.Client.RemoteEndPoint;
78
78
  NetworkStream stream = client.GetStream();
79
79
 

5

追記

2018/04/10 06:18

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -70,11 +70,12 @@
70
70
  }
71
71
  public void OnRequested(IAsyncResult res){
72
72
  TcpListener listener = res.AsyncState as TcpListener;
73
- TcpClient context = listener.EndAcceptTcpClient(res);
73
+ TcpClient client = listener.EndAcceptTcpClient(res);
74
74
 
75
75
  listener.BeginAcceptTcpClient(this.OnRequested, listener);
76
76
    // これ以下は各クライアントでやりたいこと。
77
+ client.Client.RemoteEndPoint;
77
-   // context にはクライアントのIPアドレスとStreamがあるはずです。
78
+ NetworkStream stream = client.GetStream();
78
79
 
79
80
  }
80
81
  ```

4

追記

2018/04/10 05:49

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -41,4 +41,40 @@
41
41
 
42
42
  ◇参考情報
43
43
  0. [TcpListener#BeginAcceptTcpClient](https://msdn.microsoft.com/ja-jp/library/system.net.sockets.tcplistener.beginaccepttcpclient(v=vs.110).aspx)
44
- 1. [HttpListener クラス](https://msdn.microsoft.com/ja-jp/library/system.net.httplistener(v=vs.110).aspx)
44
+ 1. [HttpListener クラス](https://msdn.microsoft.com/ja-jp/library/system.net.httplistener(v=vs.110).aspx)
45
+
46
+ ---
47
+
48
+ コンパイル通してませんが、TcpListener の場合はこのような形です。
49
+ ```C#
50
+ private TcpListener server = new TcpListener();
51
+ private readonly object locker = new object();
52
+ public Action<string> OnLogWrite;// ログ出力用
53
+ public void Start()
54
+ {
55
+ lock (this.locker)
56
+ {
57
+ // ここらへんでlistenとbindが必要なはず。
58
+ // start
59
+ this.server.Start();
60
+ this.server.BeginAcceptTcpClient(this.OnRequested, this.server);
61
+ }
62
+ }
63
+ public void Stop()
64
+ {
65
+ lock (this.locker)
66
+ {
67
+ this.server.Close();
68
+ this.server = new TcpListener();
69
+ }
70
+ }
71
+ public void OnRequested(IAsyncResult res){
72
+ TcpListener listener = res.AsyncState as TcpListener;
73
+ TcpClient context = listener.EndAcceptTcpClient(res);
74
+
75
+ listener.BeginAcceptTcpClient(this.OnRequested, listener);
76
+   // これ以下は各クライアントでやりたいこと。
77
+   // context にはクライアントのIPアドレスとStreamがあるはずです。
78
+
79
+ }
80
+ ```

3

追記

2018/04/10 05:22

投稿

umyu
umyu

スコア5846

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

2

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

2018/04/10 03:25

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -1,11 +1,11 @@
1
1
  ◇大前提
2
2
  今なら、`WebSocket`で作られた方が楽に作れるような気がしますが。
3
3
 
4
- 1,あまりコードをよく見ていませんが、`server.AcceptTcpClient`の戻り値をスレッドプールで処理するのも一つの手ですが、クライアントのメッセージを受信部分は`server.BeginGetContext`を使うのも一つの手かと。
4
+ 1,あまりコードをよく見ていませんが、`server.AcceptTcpClient`の戻り値をスレッドプールで処理するのも一つの手ですが、クライアントのメッセージを受信部分は非同期処理の`server.BeginAcceptTcpClient`を使うのも一つの手かと。
5
5
  2,`RunRecvMessageAsync`内で、 `server = new TcpListener(localAddr, PortnumSV);`を行うのではなく。`StartServer`と`StopSever`で行ってください。
6
6
 
7
7
  3,`TcpListener`を使っても最終的には独自の通信プロトコルを作成する必要があるため、`TcpListener`ではなく`HttpListener`を使うと、プロトコルのデバック作業が楽になります。
8
- 動作確認してませんが、こんな感じです。
8
+ 動作確認してませんが、サンプルソースです雰囲気を感じ取ってくださいな
9
9
  ```C#
10
10
  private HttpListener server = new HttpListener();
11
11
  private readonly object locker = new object();
@@ -35,5 +35,9 @@
35
35
    // 以下はやりたいこと。
36
36
  }
37
37
  ```
38
- 4.変数:`status`をクライアントの接続の度に変更しているのも複数接続で、破綻しているのではないでしょうか。
38
+ 4.`RunRecvMessageAsync`メソッド内で、変数:`status`をクライアントの接続の度に変更しているのも複数接続で、破綻しているのではないでしょうか。
39
- 5,画面やログの書き出しは`action`を定義すると便利です。スレッドセーフを意識してくださいな。
39
+ 5,画面やログの書き出しは`action`を定義すると便利です。スレッドセーフを意識してくださいな。
40
+
41
+ ◇参考情報
42
+ 0. [TcpListener#BeginAcceptTcpClient](https://msdn.microsoft.com/ja-jp/library/system.net.sockets.tcplistener.beginaccepttcpclient(v=vs.110).aspx)
43
+ 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

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