質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.12%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

サーバ

サーバは、 クライアントサーバモデルにおいてクライアントからの要求に対し 何らかのサービスを提供するプログラムを指す言葉です。 また、サーバーソフトウェアを稼動させているコンピュータ機器そのもののことも、 サーバーと呼ぶ場合もあります。

解決済

C# TCP通信の複数クライアント

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

サーバ

サーバは、 クライアントサーバモデルにおいてクライアントからの要求に対し 何らかのサービスを提供するプログラムを指す言葉です。 また、サーバーソフトウェアを稼動させているコンピュータ機器そのもののことも、 サーバーと呼ぶ場合もあります。

2回答

0リアクション

0クリップ

14334閲覧

投稿2018/04/10 01:45

編集2018/04/10 02:33

現在Visualstudioにてwindowsフォームアプリケーションでチャットアプリを作成しています。
下記は1対1の通信のサーバ側のコードです。
そこから複数クライアントに対応したいと思っています。
イメージでは接続できたクライアントをスレッドに渡し、待ち受け側はそのままループで頭に戻り受付再開するのかと思い、取得したポートナンバを参照渡し(ref)で渡そうと考えたのですがうまくいきません。
詳細->うまくいかない内容ですが、
非同期メソッドにて参照渡しができない点。ですのでいきなり行き詰りました。。

なにか良い方法はないでしょうか?
よろしくお願いします!

C#

/// <summary> /// 待ち受けボタンクリック処理 /// </summary> /// <param name="sender">オブジェクト</param> /// <param name="e">イベント</param> private void WaitServerBtn_Click(object sender, EventArgs e) { try { if (status != SeverStatus.IDLE) { StopSever(); } else { string ipAddress = this.getIpAdd1.IpAddress; string portString = this.myPortEdit.Text; port = Convert.ToInt32(portString); StartServer(port); } } catch (Exception exept) { MessageBox.Show(exept.Message); } } /// <summary> /// サーバー側スレッド処理 /// </summary> /// <param name="PortnumSV">ポート番号</param> void StartServer(int PortnumSV) { Task.Factory.StartNew(() => { RunRecvMessageAsync(PortnumSV); }); } /// <summary> /// 非同期受信メッセージ処理 /// </summary> public async void RunRecvMessageAsync(int PortnumSV) { status = SeverStatus.CONNECT_INIT; // クライアント接続&ネットストリームの初期化 TcpClient client = null; NetworkStream stream = null; try { IPAddress localAddr = IPAddress.Parse("127.0.0.1"); // IPアドレスの設定*今回はローカルしか使わないので直値 // サーバーを開始 server = new TcpListener(localAddr, PortnumSV); server.Start(); Byte[] bytes = new Byte[17]; //待機中の間ループして探し続ける while (true) { switch (status) { case SeverStatus.CONNECT_INIT: SafeSetLable(Properties.Resources.ConnectWait); //接続待機中のラベル表示 this.WaitServerBtn.Invoke(new Action(() => { this.WaitServerBtn.Text = Properties.Resources.Cutting; //待ち受けボタンを切断に変更 })); status = SeverStatus.CONNECT_ACCEPT_WAIT; break; // ステータス = 待ち受けの時 case SeverStatus.CONNECT_ACCEPT_WAIT: if (server.Pending()) { client = server.AcceptTcpClient(); // クライアント接続待ち //クライアント接続前にサーバ切断するとerr! stream = client.GetStream(); // ストリーム取得 SafeSetLable(Properties.Resources.Connected); // 接続されましたのラベル表示 status = SeverStatus.CONNECTED; //ステータス = 接続中 } break; // ステータス = 接続中の時 case SeverStatus.CONNECTED: // メッセージを受信 // 読み込むデータが存在する? if (stream.DataAvailable) { // データを読み込む int readlen = stream.Read(bytes, 0, bytes.Length); if (readlen != 0) { String data = System.Text.Encoding.UTF8.GetString(bytes, 0, readlen); // UIスレッド以外から呼び出された時のためにinvokeする this.ChatText.Invoke(new Action(() => { this.ChatText.Text += (Properties.Resources.Partner + ":" + data + "\r\n"); })); } } // クライアントから切断された? if (client.Client.Poll(1000, SelectMode.SelectRead) && (client.Client.Available == 0)) { stream.Dispose(); // ストリームの開放 stream = null; client.Close(); // クライアントとの接続終了 client = null; status = SeverStatus.CONNECT_ACCEPT_WAIT; } break; // ステータス = アイドルの時 case SeverStatus.IDLE: default: break; } // ループ終わり // 続きの実行は適当な空いているスレッドに割り当てるようにする await Task.Delay(1).ConfigureAwait(false); } } catch (SocketException socketEx) { // MessageBox.Show(except.Message); if (socketEx.ErrorCode == WSAEINTR) { MessageBox.Show("クライアント側で通信が切断されました。\n"); } } finally { if (stream != null) { stream.Dispose(); stream = null; } if (client != null) { client.Close(); client = null; } if (server != null) { server.Stop(); server = null; SafeSetLable("切断されました"); this.WaitServerBtn.Invoke(new Action(() => { this.WaitServerBtn.Text = "待ち受け"; this.WaitServerBtn.Enabled = true; })); } status = SeverStatus.IDLE; // ステータス = アイドル } } /// <summary> /// サーバー側スレッド処理 /// </summary> /// <param name="PortnumSV">ポート番号</param> void StartServer(int PortnumSV) { Task.Factory.StartNew(() => { RunRecvMessageAsync(PortnumSV); }); } private async void StopSever() { if (status != SeverStatus.IDLE) { this.WaitServerBtn.Enabled = false; server.Stop(); while (status != SeverStatus.IDLE) { await Task.Delay(100); //Task.waitで待つとデッドロックする } } }

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

y_waiwai

2018/04/10 02:25

うまくいかないとは、なにがどう、うまくいかないんでしょうか

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.12%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

サーバ

サーバは、 クライアントサーバモデルにおいてクライアントからの要求に対し 何らかのサービスを提供するプログラムを指す言葉です。 また、サーバーソフトウェアを稼動させているコンピュータ機器そのもののことも、 サーバーと呼ぶ場合もあります。