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

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

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

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

WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

Q&A

解決済

2回答

1556閲覧

Websocket-sharpを用いてサーバー側のGUIアプリを作りたい

alicealice

総合スコア5

C#

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

WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

0グッド

0クリップ

投稿2020/10/11 03:55

編集2020/10/11 04:49

前提・実現したいこと

C#超初心者です。
WindowsFormでWebsocket通信を行うアプリ(サーバーサイド)を作ろうとしています。クライアント側から受信したメッセージをテキストボックス上に表示させるようなアプリを作りたく下記のようなコードを書いたのですが、テキストボックスへの表示部分がうまくいかず困っています。

少し調べてみた結果、GUIで表示させるform1と受信時にインスタンスとして呼び出しているform1が異なることが原因であることがわかったのですが、Hogeクラス内でのform1の適切な呼び出し方がわかりません。。。
(因みにwebsocket-sharpライブラリの仕様上引数ありコンストラクタが使えないため、Hogeクラスのインスタンス作成時の引数としてform1を呼び出すことはできなさそうです…)

あまりにも未熟すぎるが故の質問ですが、どなたかご教授いただければ幸いです。よろしくお願いいたします。

発生している問題・エラーメッセージ

例外がスローされました: 'System.InvalidOperationException' (websocket-sharp.dll の中)
型 'System.InvalidOperationException' の例外が websocket-sharp.dll で発生しましたが、ユーザー コード内ではハンドルされませんでした
The underlying listener has failed to start.

該当のソースコード(Form1.cs)

c#

1 2using System; 3using System.Collections.Generic; 4using System.ComponentModel; 5using System.Data; 6using System.Drawing; 7using System.Linq; 8using System.Text; 9using System.Threading.Tasks; 10using System.Windows.Forms; 11using WebSocketSharp; 12using WebSocketSharp.Net; 13using WebSocketSharp.Server; 14 15namespace sample_websocketGUI 16{ 17 public partial class Form1 : Form 18 { 19 public Form1() 20 { 21 InitializeComponent(); 22 23 WebSocketServer server = new WebSocketServer(8080); //サーバの設立 24 server.AddWebSocketService<Hoge>("/"); //サーバの設定 25 server.Start(); 26 27 28 } 29 30 private void textBox1_TextChanged(object sender, EventArgs e) 31 { 32 33 } 34 35 //受信時のテキストボックス表示用メソッド 36 public void textshow(string str) 37 { 38 textBox1.Text = str; 39 40 } 41 42 } 43 44 public class Hoge : WebSocketBehavior 45 { 46 47 //受信時に呼び出されるメソッド 48 protected override void OnMessage(MessageEventArgs e) 49 { 50 51       //エラーの要因と思われる箇所 52       Form1 f1 = new Form1(); 53         54 f1.textshow(e.Data); 55 //Console.WriteLine(e.Data); //デバッグ用 56 57 } 58 59 60 } 61 62 63} 64

補足情報(FW/ツールのバージョンなど)

以下のツール、ライブラリを使用

・WindowsForms (Windows 10 Pro)
・Websocket-sharp
https://github.com/sta/websocket-sharp

・テスト(クライアント側)
C:\Users*** >wscat -c ws://localhost:8080

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2020/10/11 04:07

インデントが崩れるので、ソースコードは「コードの挿入」で記入してください
alicealice

2020/10/11 04:51

使い勝手がわかっておらず申し訳ございません、修正いたしました
guest

回答2

0

ベストアンサー

Hoge側にForm用のプロパティを追加して、WebSocketServer.AddWebSocketService に初期化アクションを追加すれば、多分ご希望の動作になりそうな気がします。

(Hoge側)

C#

1 public class Hoge : WebSocketBehavior 2 { 3 //フォームインスタンス記憶用のプロパティ 4 public Form1 Form { get; set; } 5 6 //受信時に呼び出されるメソッド 7 protected override void OnMessage(MessageEventArgs e) 8 { 9 Form.textshow(e.Data); 10 } 11 }

(Form1コンストラクタ)

C#

1 public Form1() 2 { 3 InitializeComponent(); 4 5 WebSocketServer server = new WebSocketServer(8080); //サーバの設立 6 server.AddWebSocketService<Hoge>("/", (Hoge hoge) => hoge.Form = this); 7 server.Start(); 8 } 9

###(適当に考えた別の方法)
HogeでForm側の処理をさせずに、Form内のメソッドへ流してみる。
(Hoge側)

C#

1 public delegate void WebSocketMeesageHandler(WebSocketBehavior sender, MessageEventArgs e); 2 3 public class Hoge : WebSocketBehavior 4 { 5 public WebSocketMeesageHandler CustomMessageHandler; 6 7 protected override void OnMessage(MessageEventArgs e) 8 { 9 //Hoge側はCustomMessageHandlerが設定されていたらそこへ流す 10 CustomMessageHandler?.Invoke(this, e); 11 } 12 } 13}

(Form1側)

C#

1 public partial class Form1 : Form 2 { 3 public Form1() 4 { 5 InitializeComponent(); 6 7 WebSocketServer server = new WebSocketServer(8080); //サーバの設立 8 server.AddWebSocketService<Hoge>("/", (Hoge hoge) => hoge.CustomMessageHandler = this.OnMessage); 9 server.Start(); 10 } 11 12 protected void OnMessage(WebSocketBehavior sender, MessageEventArgs e) 13 { 14 //Form内でOnMessage処理をする 15 textshow(e.Data); 16 }

投稿2020/10/11 05:22

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

alicealice

2020/10/12 02:08

ご回答ありがとうございます。 両方法で想定していた動作を確認できました!誠に助かります。 デリゲートやInvoke、ラムダ式についての理解が必要そうですね、勉強いたします。
退会済みユーザー

退会済みユーザー

2020/10/12 02:18 編集

デリゲートは実行させたいメソッドを変数のように受け渡しする時に使用します。 解決したのであれば、ベストアンサーの設定をお願いします。
alicealice

2020/10/12 05:15

大変恐縮ではございますが、追加で質問させていただきます。 反対にGUI(サーバー)側からボタンを押したタイミングでメッセージをクライアントに送信するという機能を実装する場合、どのような処理を追加すればよろしいでしょうか?? WebSocketBehaviorを継承したHogeクラスにSend(string data) メソッドがあるのですが、このメソッドをForm1に呼び出す方法がわかりません…
退会済みユーザー

退会済みユーザー

2020/10/12 06:29 編集

SendはprotectedメソッドなのでForm側からは呼べないですね。 スマートじゃないかもしれませんが、Hoge側にSend処理をするpublicメソッド追加するしかないんじゃないでしょうか。 Hogeのインスタンスは、初期化アクションでFormのメンバ変数に格納する処理を入れればよいかと思います。
alicealice

2020/10/12 06:49

ご回答ありがとうございます! 仰って下さった方法を元に実装できました!本当に感謝です!
guest

0

こんにちは。

alicealiceさんの予想されている通り、OnMessageメソッド内で新しくForm1を作ってしまっているのが原因になります。
正しくForm1を参照するためには、Hogeクラス内にForm1型のフィールドを作り、正しいForm1の参照先を記憶させておく必要があります。

Form1クラス内でHogeクラスをnewしているはずですが、そこにはおそらく以下のように記述されているものと思います。

C#

1Hoge hoge = new Hoge();

ここの引数にForm1の参照を入れてやって、Hogeクラスの初期化時にForm1の参照を記憶させるようにすると良いでしょう。

C#

1Hoge hoge = new Hoge(this);

C#

1 2public class Hoge : WebSocketBehavior 3{ 4 private Form1 form; 5 6 public Hoge(Form1 form) 7 { 8 this.form = form; 9 } 10 11 //受信時に呼び出されるメソッド 12 protected override void OnMessage(MessageEventArgs e) 13 { 14 form.textshow(e.Data); 15 //Console.WriteLine(e.Data); //デバッグ用 16 } 17}

###その他気になったこと

  • もしただTCP/IP通信をするだけでも事足りるようなら、ライブラリを使ったりしなくても簡単に実装出来ます。その場合はこちらが参考になると思います。
  • teratailにはコードを表示させるための機能があるので、それを使って頂けると見易くてありがたいです。

投稿2020/10/11 04:08

編集2020/10/11 04:20
Automatic9045

総合スコア313

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

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

alicealice

2020/10/11 05:01

ご回答ありがとうございます。 >> teratailにはコードを表示させるための機能があるので、それを使って頂けると見易くてありがたいです。 使い勝手がわかっておらず申し訳ございません、コードの表示を修正いたしました。 >>もしただTCP/IP通信をするだけでも事足りるようなら、ライブラリを使ったりしなくても簡単に実装出来ます。その場合はこちらが参考になると思います。 websocketを使う前提なのでどうしてもwebsocket関連のライブラリを使う必要があります… server.AddWebSocketService<Hoge>("/"); //サーバの設定 このタイミングでHogeクラスをnewしていると思われるのですが、質問文でも述べた通り初期化時に引数をわたすことができないため仰ってる方法では実現できなさそうです…
Automatic9045

2020/10/11 05:40

>> このタイミングでHogeクラスをnewしていると思われるのですが、 間違いなくその通りですね。見落としていました…… オブジェクト指向的にはradianさんの「適当に考えた別の方法」が最適解だと思いますので、そちらを参考になさって下さい。
alicealice

2020/10/12 02:11

ありがとうございます!無事想定した動作の確認ができました。 デリゲート等わからない文法がでできたため引き続き勉強いたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問