現在Visualstudioにてwindowsフォームアプリケーションでチャットアプリを作成しています。
下記は1対1の通信のサーバ側のコードです。
そこから複数クライアントに対応したいと思っています。
イメージでは接続できたクライアントをスレッドに渡し、待ち受け側はそのままループで頭に戻り受付再開するのかと思い、取得したポートナンバを参照渡し(ref)で渡そうと考えたのですがうまくいきません。
詳細->うまくいかない内容ですが、
非同期メソッドにて参照渡しができない点。ですのでいきなり行き詰りました。。
なにか良い方法はないでしょうか?
よろしくお願いします!
C#
1 /// <summary> 2 /// 待ち受けボタンクリック処理 3 /// </summary> 4 /// <param name="sender">オブジェクト</param> 5 /// <param name="e">イベント</param> 6 private void WaitServerBtn_Click(object sender, EventArgs e) 7 { 8 try 9 { 10 if (status != SeverStatus.IDLE) 11 { 12 StopSever(); 13 } 14 else 15 { 16 string ipAddress = this.getIpAdd1.IpAddress; 17 string portString = this.myPortEdit.Text; 18 port = Convert.ToInt32(portString); 19 20 StartServer(port); 21 } 22 } 23 catch (Exception exept) 24 { 25 MessageBox.Show(exept.Message); 26 } 27 } 28/// <summary> 29 /// サーバー側スレッド処理 30 /// </summary> 31 /// <param name="PortnumSV">ポート番号</param> 32 void StartServer(int PortnumSV) 33 { 34 Task.Factory.StartNew(() => 35 { 36 RunRecvMessageAsync(PortnumSV); 37 }); 38 } 39 /// <summary> 40 /// 非同期受信メッセージ処理 41 /// </summary> 42 public async void RunRecvMessageAsync(int PortnumSV) 43 { 44 status = SeverStatus.CONNECT_INIT; 45 46 // クライアント接続&ネットストリームの初期化 47 TcpClient client = null; 48 NetworkStream stream = null; 49 50 try 51 { 52 IPAddress localAddr = IPAddress.Parse("127.0.0.1"); // IPアドレスの設定*今回はローカルしか使わないので直値 53 54 // サーバーを開始 55 server = new TcpListener(localAddr, PortnumSV); 56 server.Start(); 57 58 Byte[] bytes = new Byte[17]; 59 60 //待機中の間ループして探し続ける 61 while (true) 62 { 63 switch (status) 64 { 65 case SeverStatus.CONNECT_INIT: 66 SafeSetLable(Properties.Resources.ConnectWait); //接続待機中のラベル表示 67 this.WaitServerBtn.Invoke(new Action(() => 68 { 69 this.WaitServerBtn.Text = Properties.Resources.Cutting; //待ち受けボタンを切断に変更 70 })); 71 72 status = SeverStatus.CONNECT_ACCEPT_WAIT; 73 break; 74 75 // ステータス = 待ち受けの時 76 case SeverStatus.CONNECT_ACCEPT_WAIT: 77 if (server.Pending()) 78 { 79 client = server.AcceptTcpClient(); // クライアント接続待ち //クライアント接続前にサーバ切断するとerr! 80 stream = client.GetStream(); // ストリーム取得 81 SafeSetLable(Properties.Resources.Connected); // 接続されましたのラベル表示 82 83 status = SeverStatus.CONNECTED; //ステータス = 接続中 84 } 85 break; 86 87 // ステータス = 接続中の時 88 case SeverStatus.CONNECTED: 89 // メッセージを受信 90 // 読み込むデータが存在する? 91 if (stream.DataAvailable) 92 { 93 // データを読み込む 94 int readlen = stream.Read(bytes, 0, bytes.Length); 95 if (readlen != 0) 96 { 97 String data = System.Text.Encoding.UTF8.GetString(bytes, 0, readlen); 98 // UIスレッド以外から呼び出された時のためにinvokeする 99 this.ChatText.Invoke(new Action(() => 100 { 101 this.ChatText.Text += (Properties.Resources.Partner + ":" + data + "\r\n"); 102 })); 103 } 104 } 105 // クライアントから切断された? 106 if (client.Client.Poll(1000, SelectMode.SelectRead) && (client.Client.Available == 0)) 107 { 108 stream.Dispose(); // ストリームの開放 109 stream = null; 110 client.Close(); // クライアントとの接続終了 111 client = null; 112 113 status = SeverStatus.CONNECT_ACCEPT_WAIT; 114 } 115 break; 116 // ステータス = アイドルの時 117 case SeverStatus.IDLE: 118 default: 119 break; 120 } // ループ終わり 121 122 // 続きの実行は適当な空いているスレッドに割り当てるようにする 123 await Task.Delay(1).ConfigureAwait(false); 124 } 125 } 126 catch (SocketException socketEx) 127 { 128 // MessageBox.Show(except.Message); 129 if (socketEx.ErrorCode == WSAEINTR) 130 { 131 MessageBox.Show("クライアント側で通信が切断されました。\n"); 132 } 133 134 } 135 finally 136 { 137 if (stream != null) 138 { 139 stream.Dispose(); 140 stream = null; 141 } 142 if (client != null) 143 { 144 client.Close(); 145 client = null; 146 } 147 if (server != null) 148 { 149 server.Stop(); 150 server = null; 151 SafeSetLable("切断されました"); 152 this.WaitServerBtn.Invoke(new Action(() => 153 { 154 this.WaitServerBtn.Text = "待ち受け"; 155 this.WaitServerBtn.Enabled = true; 156 })); 157 } 158 status = SeverStatus.IDLE; // ステータス = アイドル 159 } 160 } 161 /// <summary> 162 /// サーバー側スレッド処理 163 /// </summary> 164 /// <param name="PortnumSV">ポート番号</param> 165 void StartServer(int PortnumSV) 166 { 167 Task.Factory.StartNew(() => 168 { 169 RunRecvMessageAsync(PortnumSV); 170 }); 171 } 172 private async void StopSever() 173 { 174 if (status != SeverStatus.IDLE) 175 { 176 this.WaitServerBtn.Enabled = false; 177 server.Stop(); 178 179 while (status != SeverStatus.IDLE) 180 { 181 await Task.Delay(100); //Task.waitで待つとデッドロックする 182 } 183 } 184 } 185
回答2件
あなたの回答
tips
プレビュー