こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

VB6のwinsockでconnectできない

socketでconnectすると、sckclosingとなって通信できない。
機械との通信プログラムをつくるため、インターネットから以下のようなサンプルを取って、同一コンピュータ、または異なるコンピュータ間で通信しようとした(一部省略、改変)が、stateが8となってしまいます。socketを使うのは初めてで、皆目見当がつきません。よろしくお願いします。
サーバー側
Private Sub Form_Load()
Winsock1.LocalPort = 1001
Winsock1.Listen
--------
End Sub

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Dim dat As String, ans As String
Dim n As Integer
Winsock1.GetData dat
Text1.Text = dat
Winsock1.SendData "わかりません"
End Sub

Private Sub Form_Load()
Text1.Text = "abc" (正しいコンピュータ名を入れた)
Winsock1.Close
LabCon.Caption = "Closed": LabCon.BackColor = vbWhite
End Sub
クライアント側
Private Sub Command1_Click()
Winsock1.Close
Winsock1.RemoteHost = Text1.Text
Winsock1.RemotePort = 1001 'ポート番号設定
Winsock1.Connect
Do While (Winsock1.State <> sckConnected)
LabCon.Caption = Winsock1.State
DoEvents
Loop
End Sub
クライアントでcommand1ボタンをクリックすると最初はstateが0、ループに入ると8となって出られません。WindowsXP、Vista共に同じ結果でした。

投稿日時 - 2012-09-12 22:42:12

QNo.7694625

困ってます

質問者が選んだベストアンサー

確認させてください。

・サーバのコードはそれだけ?
Winsock_Accept()は作っていませんか?
8はsckClosingで、接続を相手が解除しようとしている状態です。
つまり、接続を受け付けるコードがないと接続を受け付けることができないので、切断されてしまいます。
Winsock_AcceptにrequireIdが渡されるので、それをAcceptしてください。

Winsock1.Accept requireId ←これで、サーバが接続を受け付けます


幾つか気がついたことを。

・LocalPortの初期化
バグと言うか、仕様なのですが、Connectするまえに、LocalPortを0クリアしてあげないと、二回目の接続がエラーになります。
RemotePort=1001の次の行にでも、いれてあげてください。

・なるべくWinsockのイベントハンドラを使う
一つのイベントに作り込んでループで待つと、通信が行われなかったり、ループとループの間の変化が捉えきれなかったりします。
今回のも、もしかすると、Winsock_Connectedを使っていれば、接続が解除されていたとわかったかもしれません。
(今はVB6の環境が無くなったので、かくにんできませんので、可能性の話なのですが)

たしか、SendDataが、Doeventをいれるか、イベントハンドラを終わらせないと、送信されないはずです。
(大分前の記憶なのでうろ覚えなのですが)

投稿日時 - 2012-09-13 15:52:47

お礼

ご指摘の通りでした。ありがとうございます。

この通信は初めてで、Listenをして、DataArraivalで受ければいいのかと思っていましたので、以下の処理があることを見落としていました。
Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
If Winsock1.State <> sckClosed Then 'Winsockの状態(閉じていない)
Winsock1.Close 'Winsockを閉じる
End If
Winsock1.Accept requestID '接続処理
End Sub
ところで、一度connectすると、SendDataとGetDataを繰り返して、最後にcloseしてよいのですか。また、多くのサンプルでLocarPortとRemotePortが同じ番号が使われていますが、このようにするものですか。また、この番号は任意でよいのですか。目的の機械は4444(変更可)です。是非これらの点も教えてください。

投稿日時 - 2012-09-13 22:13:05

ANo.2

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

ANo.2です。

・Connectの後はSendData/RecvDataで良いか?
そうなります。
ただ、注意しなければならないのは、TCPIPは一度に転送される最小バイト数が1バイトなので、少ないデータ量ならばあまり問題になりませんが、大きいデータの場合一度の受信で全部受信されません。
特にMTUを変更していなければ、通常は1460バイトを越えたあたりから、工夫が必要になります。
わたしは、この辺りを実装するのが面倒なので、Connectイベントでファイルを開き、DataAvaivalイベントで書き込んでいます。
コマンド発行/応答受信の場合は、受信データをファイルに書き込んだ後に終端文字CRLFやETX等があるか確認し、あった場合はファイルを閉じて読みこみ、解析します。

通信が全て終わったら、Closeをすればよいです。しかし、次の通信開始は、Closedイベントが発生するのを待ってください。

・RemotePortとLocalPortについて
RemotePortは、いうなれば、代表電話番号みたいなものなので、基本的に器機が指定するポートを使えば良いです。器機側のポート番号は、特別な理由がなければ、変えない方が良いでしょう。
LocalPortは、指定されていなければ、0指定でokです。
クライアント側のポート番号を固定にしてしまうと、このツールを複数立ち上げれなくなります。
(器機側が複数の接続に対応していることも必要ですが)

0指定は、実際には1025~2048のポートのうち、空いているポートをOSが割り当ててくれます。
接続先の器機が、クライアントのポートを指定しているのであればその番号を、そうでなければ0で問題ありません。

投稿日時 - 2012-09-14 10:18:01

お礼

補足の質問にまで答えていただき、ありがとうございました。

私は、新しいことを始めると、簡単なことでも、エラー情報等が出ていても、すぐにはその原因にたどり着けないことが多いです。今回は、ハードウエアも絡むのかなと思い、余計見当がつきませんでした。大変ありがとうございました。

また、今後、問題が出て、悩みそうなところも、丁寧に書いていただきありがとうございました。とりあえず、コンピュータ上でシュミレートが出来るレベルまでプログラミングができました。

投稿日時 - 2012-09-14 19:57:35

ANo.1

Protocolプロパティを指定していない、ポート番号は正しいか?

このあたりが怪しいですね。

ついでながら繋がるまでループさせるのは良くないですね。

投稿日時 - 2012-09-12 23:24:35

補足

早速にアドバイスありがとうございました。
Protocolプロパティは、入れても同じ結果でした。
ループは、上手く動かなかったのでそのようにしたまでです(当初はタイマー等をいれていました)。
ご指摘のポート番号は、全く理解していないので、インターネットのサンプルのままにしています。
目的の機械の番号は分かっているのですが、事前にコンピュータ上でシュミレートしたいと思っています。ポートの断片的な記述は見つかりましたが、理解するに至っていません。コンピュータの場合はどのように決めるのか、アドバイスまたは適当なサイトが有りましたらお教えください。

投稿日時 - 2012-09-13 00:24:21

あなたにオススメの質問