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

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

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

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

Q&A

1回答

4556閲覧

C#フォームアプリケーションでのソケット通信プログラムについて

tayamay

総合スコア0

C#

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

0グッド

0クリップ

投稿2020/09/25 02:54

前提・実現したいこと

C# フォームアプリケーションでソケット通信を行うプログラムを作成しています。

button1を押すと接続先とソケット通信を行い、
button2を押すとソケット通信を利用したコマンドのやり取りを行うようになっています。

プログラム(フォーム)を閉じるときはソケット通信をcloseするように組んでいるのですが
button1、button2、FormClosing、それぞれで最初に宣言した TcpClient client を
呼び出したいので、public partial class Form1 : Form のところで宣言してあります。

button1を押して接続がうまくできなかった場合、環境を整えてから
再度button1を押して接続トライできるようにプログラムを構成したいのですが、
下記ソースだとbutton1を押して接続がうまくできなかった時点でTcpClient clientが
消えてしまい、再度button1を押してもclientを再び宣言しなくてはいけない状態になります。

button1の中で TcpClient client を宣言してしまうと、button2、FormClosingのところで
clientの呼び出しができないため、どのようにプログラムを組めば良いか悩んでいます。

初歩的な内容になりますが、どなたかご教授頂けないでしょうか?

該当のソースコード

Visual

1using System; 2using System.Collections.Generic; 3using System.Drawing; 4using System.Threading.Tasks; 5using System.Windows.Forms; 6using System.Net.Sockets; 7using System.Net; 8using System.Threading; 9 10namespace Connect 11{ 12 public partial class Form1 : Form 13 { 14 IPAddress ipAddress = IPAddress.Parse("192.168.3.39"); //IPアドレス入力 15 int port = 2999; //接続ポート 16 17 //ソケット通信 18 public TcpClient client = new TcpClient(); 19 20 21 public Form1() 22 { 23 InitializeComponent(); 24 } 25 26 private void button1_Click(object sender, EventArgs e) 27 { 28 //ソケット通信開始 29 try 30 { 31 int timeout = 500; //接続タイムアウト時間 (msec) 32 33 Task con_task = client.ConnectAsync(ipAddress, port); //接続先から応答がないとフリーズしてしまうのでTask処理 34 if (!con_task.Wait(timeout)) // 接続拒否などは AggregateException 35 { 36 throw new SocketException(10060); // 10060 -> タイムアウト 37 } 38 else 39 { 40 MessageBox.Show("Socket通信 接続成功"); //接続成功 41 } 42 } 43 catch (SocketException) //接続エラー 44 { 45 client.Close(); 46 MessageBox.Show("Socket通信 応答無し"); 47 } 48 catch (AggregateException) //接続拒否 49 { 50 client.Close(); 51 MessageBox.Show("Socket通信 接続拒否"); 52 } 53 } 54 55 private void Form1_FormClosing(object sender, FormClosingEventArgs e) 56 { 57 client.Close(); 58 MessageBox.Show("Socket closed"); 59 } 60 61 private void button2_Click(object sender, EventArgs e) 62 { 63 if (client.Connected) 64 { 65 try 66 { 67 NetworkStream stream = client.GetStream(); 68 //データ通信の構文↓(省略) 69 // 70 // 71 } 72 73 catch (Exception) 74 { 75 MessageBox.Show("応答無し"); 76 } 77 } 78 else 79 { 80 MessageBox.Show("Socket通信 接続できていません"); 81 } 82 83 } 84 } 85} 86

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gentaro

2020/09/25 03:42

> 下記ソースだとbutton1を押して接続がうまくできなかった時点でTcpClient clientが 消えてしまい あいまいな表現はやめましょう。 消えるというのはnullになるという意味ですか? それとも何らかのエラーが発生して利用が不可能になる、という意味ですか? いずれにせよ、エラーは発生していると思われるため、そのエラーの内容を質問文に書きましょう。
tayamay

2020/09/25 03:48

あいまいな表現、申し訳御座いません。 nullになっていました。エラー内容は下記のとおりです。 Task con_task = client.ConnectAsync(ipAddress, port) ← System.NullReferenceException: オブジェクト参照がオブジェクト インスタンスに設定されていません。 接続ができなかったときにclient.Close()していますが、これをとってしまうと 再度button1を押して再接続させようとするとソケットの重複が起きてしまいます。 エラー文は下記の通りです。↓ System.InvalidOperationException: '同じソケット上で別の非同期操作の実行中に BeginConnect を呼び出すことはできません。'
guest

回答1

0

button1_Clickでnullチェックを行い、nullの場合にインスタンスを生成すればご所望の動作ができるとおもいます。

C#

1 //ソケット通信 2 public TcpClient client;

C#

1 private void button1_Click(object sender, EventArgs e) 2 { 3 if (client == null) 4 client = new TcpClient(); 5 //ソケット通信開始 6 try 7 {

投稿2020/09/25 04:32

編集2020/09/25 04:33
gentaro

総合スコア8947

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

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

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

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問