アプリ版:「スタンプのみでお礼する」機能のリリースについて

はじめまして。VB.NETで質問があります。内容は、(スレッドと)ソケットを使った「非同期」通信についてです。

マイクロソフトのページからサンプルコードをコピーして、二行のプロジェクトを作成し以下の二つのコードを追加したんですけど…(ipの指定は、GetHostNameを使っています。)


プロジェクト1:非同期クライアント ソケットの例
Button1_Click
AsynchronousClient.Main()

プロジェクト2:非同期サーバー ソケットの例
Button1_Click
AsynchronousSocketListener.Main()

マイクロソフトのページ(ソケットのコード例)
http://www.microsoft.com/japan/msdn/library/defa …


プロジェクト2のフォームが固まってしまいます。
(Waiting for a connection...を出力ウィンドウに表示したままになってしまいます。)

暫定策として、Shellを使って、サーバー(プロジェクト2のexe)を起動してみたのでが、それでも固まってしまいました。


3日間ぐらいかけてネットで検索とMSDN見たけど、分かりませんでした。キーワードは、以下の通り…
「マイクロソフト .NET スレッド フリーズ サンプルコード 非同期 マルチ select -sql」

Select フックなどの言葉も関係があるようなのですがよく分かりません。

ただ、フォーム上のボタンが押せるようになれば、解決です。

なにかキーワードだけでも、教えてください。お願いします。

A 回答 (4件)

> ■まず、クラスファイルは追加できたのですがprjServerの起動クラスの項目(clsPrj2)にどうやって追加するのか分かりませんでした。



起動クラスではなく、メインモジュール(Sub Main())でした。誤った情報を教えてしまってすいません。


> ■また、クラスファイルから(またはメインモジュールから)フォームをShowするやり方が分かりませんでした。(frmServer.show()ができませんでした。)

オブジェクト指向の概念を結構無視した作り方ですが、よければ参考にしてください。このやり方で「なんちゃってマルチスレッド」となるはずです。
※ちょいと寝ぼけ眼で書いてますんで、多少の間違いは勘弁してください。方向性は大丈夫だと思いますんで・・・。


(1)非同期サーバ起動フラグ格納クラス(仮にclsBoolとします)を作成し、publicメンバ変数(仮にboolean型のbFlag)を用意します(初期値:false)。
(2)frmServerクラスに、clsBool型のpublicメンバ変数(仮にcFlag)を追加します。
(3)Main()関数およびfrmServer.btnServer_Click()での処理を以下のようにします。

===== メインモジュール内 =====
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sub Main()
Dim cBool As clsBool
Dim frmS As frmServer

Set frmS = New frmServer
Set cBool = New clsBool

Load frmS
set frmS.cFlag = cBool
frmS.Show

Do While 1
If cBool.bFlag = true Then
exit Do
Else
DoEvents
Sleep 1000
End If
Loop

AsynchronousClient.Main '非同期サーバ起動

frmS.Hide
Unload frmS
Set frmS = Nothing
Set cBool = Nothing

End Sub

======= frmServerクラス内 =======
private sub btnServer_Click()
cFlag.bflag = true
end sub


> ■文字だけの送受信なら、tcpClientクラスやtcpListnerクラスを使って簡単にできると思うのですが、ファイルの転送もできるのでしょうか?(その際、BinaryWriterとBinaryReaderを使えばいいのでしょうか?)しかし、スレッドを使わないとファイルを送受信している間は、他に何もできないのかも??

VBでファイル転送は経験ありませんが、個人的にはftpを使ったほうがいいような気もします。
明確な回答でなくてごめんなさい。

この回答への補足

レス遅れました。
マルチタスクにするためには、監視するスレッドが必要なのですね υ

VB.NETは、買ったばかりなので、なかなか難しいです。


大変遅くなってしまいましたが、だいぶ、考え方は理解できたので、締め切ろうと思います。

ご協力ありがとうございました。
(お礼と補足が逆になった事、締め切るまでに時間がかかった事をお詫びします。)


また、機会があれば教えてください。
私は、勿論、力不足ですが、できる範囲でお返しもしたいです。

補足日時:2005/04/25 21:18
    • good
    • 0
この回答へのお礼

レス遅れました。

眠いのに一所懸命アドバイスしてくれて、ありがとうございます。

publicメンバ変数というのが、分かりませんでした。メインモジュール内で、
Public Class clsBool
Dim bFlag As Boolean = False
End Class
と書いたのですが、上手くいきませんでした。

クラスファイルを追加してもダメでした。


後は助言して頂いた方法でも、引き続き frmServer.show() ができませんでした。


これ(↓)関係ありそうですが・・・。
http://park16.wakwak.com/~mimi/dotnet/misc/worke …


もうちょっと自分で試行錯誤してみます。
またお世話になるかもしれませんが、その時は宜しくお願いします。

お礼日時:2005/03/11 17:17

>文字だけの送受信なら、tcpClientクラスやtcpListnerクラスを使って簡単にできると思うのですが、ファイルの転送もできるのでしょうか?



についてですが、

TcpClientクラス
http://www.microsoft.com/japan/msdn/library/defa …

>データを送受信するには、 GetStream メソッドを使用して
とあります

使ったことがないからよくわかっておりませんが、VB6でのWinSockコントロールのメソッドと類似しているので、MSDNを見る限りでは可能と思いますよ。

この回答への補足

実は、VB6のWinSockコントロールで、ファイル転送はできなかったですが、もっと勉強してがんばってみようと思いました。

まずは、VB6で修行(?)をつんで、VB.NETへ行きます(笑)

では、ありがとうございました。

(補足の欄にお礼を書いてしまって申し訳ありません)

補足日時:2005/04/25 21:35
    • good
    • 0
この回答へのお礼

NetworkStreamも使うみたいですね。

ただ、私はVB6でWinsockコントロールを使った事があるんですが、[winsockのオブジェクト名].SendData
(C:\Temp\Test.txt)みたいに書きたいのに書けない~って困った覚えがあります(汗)

そんなに簡単にコーディングできませんね(笑)

レスありがとうございます。

お礼日時:2005/03/11 17:26

補足説明ありがとうございます。


もしかしたら、frmServer.BtnServer_click()内でAsynchronousSocketListener.Main()をコールしていることに問題があるのではないでしょうか?

.NETに詳しくないので具体的なお答えができませんが、StartListening()内で無限ループ(待ち状態)に入っているため、BtnServer_click()メソッドが終了できずに固まっているように思います。

恐らくプロジェクト2のスタートアップ(起動クラス)をfrmServerにしているのだと思いますので、こうされてみてはどうでしょう?

(1)起動クラス(仮にclsPrj2とします)を新規作成。そのクラスではfrmServerフォームを表示後、無限ループ(非同期サーバ起動待ち)に入る。非同期サーバ起動条件は、非同期サーバ起動フラグ(仮にisStartとします)がtrueのときのみとします。(このフラグの初期状態はfalse。falseの時はしばらくSleepして再度isStartフラグをチェックする。)
(2)frmServer.BtnServer_Click()メソッドで、非同期サーバ起動開始メンバ関数(仮にclsPrj2.start()とします)をコール。この関数ではisStartをtrueにセットするのみとします。(この関数でAsynchronousSocketListener.Main()をコールするとやはりフォームが固まるように見えてしまいます。)
(3)(1)の無限ループで、isStartがtrueになるので、AsynchronousSocketListener.Main()がコールされる。

これで、ボタンが固まるということはなくなると思います。あまり自身がありませんが、これで試してみてください。もし勘違いしてたらごめんなさい。

この回答への補足

ヒントありがとうございます。
イメージは掴めたんですがコーディングが・・・。ごめんなさい。

■まず、クラスファイルは追加できたのですがprjServerの起動クラスの項目(clsPrj2)にどうやって追加するのか分かりませんでした。

ですが、すでに選択できるクラスが AsynchronousSocketListener, frmServer, sub main となっていたので、AsynchronousSocketListenerとしてみました所、フォームが固まるという問題は解決しました。そもそもfrmServerを表示しないという奇策ですが・・・。

「btnServer_click()メソッドが終了できず」という表現がすごく参考になりました。

"<QUIT>"という文字が送られてきた時はサーバを終了するようにして、待ち状態の解除をするようにしました。

■また、クラスファイルから(またはメインモジュールから)フォームをShowするやり方が分かりませんでした。(frmServer.show()ができませんでした。)

Dim frmServer1 As New prjServer.frmServer
frmServer1.show()

と書いたのですが、frmServer1の「宣言が必要です」とでまして、ビルドエラーになってしまいます。

■なんか私がやっている事は、マルチスレッドのメリットを相殺している様な気がしてきました。
やっぱりスレッドを使わないでやるしかないのかな、私には。

Public Sub New()
End Sub 'New
がヒントなんでしょうかね?(汗)(オーバーロード??)

■文字だけの送受信なら、tcpClientクラスやtcpListnerクラスを使って簡単にできると思うのですが、ファイルの転送もできるのでしょうか?(その際、BinaryWriterとBinaryReaderを使えばいいのでしょうか?)しかし、スレッドを使わないとファイルを送受信している間は、他に何もできないのかも??

どなたかご存知の方があれば、ご教授ください。
的外れなことをしていたらごめんなさい>Musaffahさん
もうちょっと、がんばってみます。

補足日時:2005/03/08 21:24
    • good
    • 0

VB.NETはよくわからないので、何もお手伝いできないかと思いますが、その前に状況をもう少し確認させてください。



(1)「プロジェクト2のButton1をクリックしたら固まる」という解釈でいいですか?
(2)その時、プロジェクト1は起動している状態ですか?また、プロジェクト2.Button1をクリックした後にプロジェクト1.Button1をクリックしてその状態になるの(要はソケット通信処理が終了しているのに・・・何故?)ですか?
(3)フォーム上にはButton1以外にもボタンがあるのですか?

この回答への補足

すみません、補足します。
(1)はい、そうです。
(2)プロジェクト2.Button1(サーバ)を押すとListen状態になり、プロジェクト1.Button1(クライアント)を押す度に、データが送受信され、サーバー側の出力ウィンドウに以下の様に表示されます。

Read 19 bytes from socket.
Data : This is a test<EOF>
Sent 19 bytes to client.

プロジェクト2.Button1(サーバ)を押した時点で、フォームが固まります。

ただし・・・
 サーバプロジェクトは、(出力ウィンドウを見る必要がある為)VB.NET で実行しています。
 クライアントは、ビルド済みの exe 本体から、起動してます。

(3)ないです。
サンプルコードをコピーして、フォームにあるボタンを押すと、非同期クライアントのmainと非同期サーバー ソケットのmainをCallするようになってます。


サンプルコードをそのまま使えるのなら、プログラマーは要らないわけで、大変皆様に失礼な質問なのですが、先に進む見込みがなくなってしまったので、ここで質問致しました。ヒントを下されば幸いです。

分かりにくいので、frmServer, btnServer, frmClient, btnClientと名前をつけます。

補足日時:2005/03/06 17:06
    • good
    • 0
この回答へのお礼

問題点の整理をして頂いてどうもありがとうございました。

お礼日時:2005/04/25 21:34

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!