DOBON.NET DOBON.NETプログラミング掲示板過去ログ

VBでのリモート通信

環境/言語:[Windows Vista, VB.Net 2010]
分類:[.NET]

2013/01/25(Fri) 16:34:42 編集(投稿者)
2013/01/24(Thu) 22:30:54 編集(投稿者)
2013/01/24(Thu) 22:30:48 編集(投稿者)

VBで、異なるPCにメッセージを表示できるプログラムを組みたいと思っています。たとえば、メッセージを送信するPCをA、受信するPCをBとした場合、
A側のプログラムにメッセージを入力して送信

インターネット経由でB側のプログラムにメッセージが送信される

B側のプログラムで(ダイアログ等によって)メッセージが表示

といった様なものを作りたいです。B側の特定には、IPアドレスを用いたいと思っています。

以上の様なプログラムの組み方を教えていただきたいです。よろしくお願い申し上げます。
何が問題点なのでしょうか?
質問内容はどんな技術を用いて実現すれば良いのかということでしょうか?
TCPIPにて送信するアプリと、TCPIPにて受信するアプリを作ったらどうでしょうか?
■No31258に返信(kikuさんの記事)
> 何が問題点なのでしょうか?
説明不足で申し訳ありませんでした。掲示板等に不慣れなものでして・・。
> 質問内容はどんな技術を用いて実現すれば良いのかということでしょうか?
その通りです。推測をさせるような質問、申し訳ありませんでした。
> TCPIPにて送信するアプリと、TCPIPにて受信するアプリを作ったらどうでしょうか?
 私が、とてつもなく初心者であるため、TCPIPというものが、解りません。ご説明くださいませんでしょうか。よろしくお願い申し上げます。
>  私が、とてつもなく初心者であるため、TCPIPというものが、解りません。ご説明くださいませんでしょうか。よろしくお願い申し上げます。

そんなの「TCPIPとは」とかでググればいくらでも説明出てきます
2013/01/26(Sat) 08:54:05 編集(投稿者)
2013/01/25(Fri) 23:48:39 編集(投稿者)

■No31260に返信(K.Mさんの記事)
>> 私が、とてつもなく初心者であるため、TCPIPというものが、解りません。ご説明くださいませんでしょうか。よろしくお願い申し上げます。
>
> そんなの「TCPIPとは」とかでググればいくらでも説明出てきます
いろいろと申し訳ありませんでした。一応、Googleで調べたのですが、要はどのようなものか解らなかったものでして...
もう一度、専門用語の一つ一つから読み直したところ、Tipsの中に、確認しました。しかし、以下のソースコードを実行したところ、クライアントソフト側で、次の様なエラーが発生しました。

System.Net.Sockets.SocketException はハンドルされませんでした。
ErrorCode=10061
Message=対象のコンピュータによって拒否されたため、接続できませんでした。 [::1]:2001
NativeErrorCode=10061
Source=System
StackTrace:
場所 System.Net.Sockets.TcpClient..ctor(String hostname, Int32 port)
場所 client.Module1.Client.Main() 場所 D:\VB\client\client\Module1.vb:行 17
場所 client.Module1.Main() 場所 D:\VB\client\client\Module1.vb:行 4
場所 System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
場所 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
場所 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
場所 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
場所 System.Threading.ThreadHelper.ThreadStart()
InnerException:




ソースコード
サーバー
Imports System
Module Module1

Sub Main()
Server.Main()
End Sub

Class Server
'エントリポイント
Public Shared Sub Main()
'文字コードを指定する
Dim enc As System.Text.Encoding = System.Text.Encoding.UTF8

'ローカルIPアドレスでListenを開始する
Dim host As String = "localhost"
Dim port As Integer = 2001
Dim ipAdd As System.Net.IPAddress = _
System.Net.Dns.Resolve(host).AddressList(0)
Dim listener As New System.Net.Sockets.TcpListener(ipAdd, port)
listener.Start()
Console.WriteLine("Port{0}のListenを開始しました。", port)

'接続要求があったら受け入れる
Dim tcp As System.Net.Sockets.TcpClient = _
listener.AcceptTcpClient()
Console.WriteLine("クライアントが接続しました。")
'NetworkStreamを取得
Dim ns As System.Net.Sockets.NetworkStream = tcp.GetStream()

'クライアントから送られたデータを受信する
Dim ms As New System.IO.MemoryStream
Dim resBytes(256) As Byte
Dim resSize As Integer
Do
'データの一部を受信する
resSize = ns.Read(resBytes, 0, resBytes.Length)
'Readが0を返した時はクライアントが切断したと判断
If resSize = 0 Then
Console.WriteLine("クライアントが切断しました。")
Console.ReadLine()
Return
End If
'受信したデータを蓄積する
ms.Write(resBytes, 0, resSize)
Loop While ns.DataAvailable
'受信したデータを文字列に変換
Dim resMsg As String = enc.GetString(ms.ToArray())
ms.Close()
Console.WriteLine(resMsg)

'クライアントにデータを送信する
Dim sendMsg As String = resMsg.Length.ToString() + "文字"
'文字列をByte型配列に変換
Dim sendBytes As Byte() = enc.GetBytes(sendMsg)
'データを送信する
ns.Write(sendBytes, 0, sendBytes.Length)
Console.WriteLine(sendMsg)

'閉じる
ns.Close()
tcp.Close()
Console.WriteLine("切断しました。")

'リスナを閉じる
listener.Stop()
Console.WriteLine("Listenerを閉じました。")

Console.ReadLine()
End Sub
End Class
End Module



クライアント
Module Module1

Sub Main()
Client.Main()
End Sub

Public Class Client
Shared Sub Main()
'文字コードを指定する
Dim enc As System.Text.Encoding = System.Text.Encoding.UTF8

'サーバーのホスト名とポート番号
Dim host As String = "localhost"
Dim port As Integer = 2001

'TcpClientを作成し、サーバーと接続する
Dim tcp As New System.Net.Sockets.TcpClient(host, port)
Console.WriteLine("サーバーと接続しました。")

'NetworkStreamを取得する
Dim ns As System.Net.Sockets.NetworkStream = tcp.GetStream()

'サーバーにデータを送信する
'送信するデータを入力
Dim sendMsg As String = Console.ReadLine()
'何も入力されなかった時は切断する
If sendMsg = "" Then
tcp.Close()
Return
End If
'文字列をByte型配列に変換
Dim sendBytes As Byte() = enc.GetBytes(sendMsg)
'データを送信する
ns.Write(sendBytes, 0, sendBytes.Length)
Console.WriteLine(sendMsg)

'サーバーから送られたデータを受信する
Dim ms As New System.IO.MemoryStream
Dim resBytes(256) As Byte
Dim resSize As Integer
Do
'データの一部を受信する
resSize = ns.Read(resBytes, 0, resBytes.Length)
'Readが0を返した時はサーバーが切断したと判断
If resSize = 0 Then
Console.WriteLine("サーバーが切断しました。")
Console.ReadLine()
Return
End If
'受信したデータを蓄積する
ms.Write(resBytes, 0, resSize)
Loop While ns.DataAvailable
'受信したデータを文字列に変換
Dim resMsg As String = enc.GetString(ms.ToArray())
ms.Close()
Console.WriteLine(resMsg)

'閉じる
ns.Close()
tcp.Close()
Console.WriteLine("切断しました。")

Console.ReadLine()
End Sub
End Class
End Module


この原因と解決法をお教えいただけませんでしょうか。また、これには、ルーター等における設定が必要であったりするのでしょうか。

尚、インターネットプロバイダーは、auで、au光を利用しています。
■No31262に返信(金田武さんの記事)
>>そんなの「TCPIPとは」とかでググればいくらでも説明出てきます
> いろいろと申し訳ありませんでした。一応、Googleで調べたのですが、要はどのようなものか解らなかったものでして...

ネットワークの知識が皆無の状態で見よう見まねで作るとセキュリティ上の問題を抱えたサーバーを作ってしまう可能性があります。
インターネットを通じて公開される際には、サーバーを公開することによって生じるリスクについて考えてみてください。

たとえば、あなた以外が接続して情報を引き出せてしまう、不正に操作できてしまうなど。


> System.Net.Sockets.SocketException はハンドルされませんでした。
> ErrorCode=10061
> Message=対象のコンピュータによって拒否されたため、接続できませんでした。 [::1]:2001

サーバー側のプログラムを実行していない状態でクライアント側のプログラムを実行したか、サーバー側のポートが Windows ファイアウォールなどで制限されているかでしょうか。
サーバー側を起動していなかったのであれば”先に”起動してください。同時に実行だと、サーバー側の準備が終わる前にクライアント側がエラーになることもあると思われるので。


> この原因と解決法をお教えいただけませんでしょうか。また、これには、ルーター等における設定が必要であったりするのでしょうか。

そういう考えが出てくる時点で、知識不足を指摘せざる得ません。
localhost で公開、localhost に接続する上で、ルーターは出てきませんので…。

もちろん、最終のゴール(インターネットを通じて公開すること)に対しては必要なことです。
確かに、私の知識不足については、否定できません。セキュリティ上の問題のあるサーバーを作ってしまう可能性もある事は承知しております。ですが、このプログラムは、不足した知識を補うために作成しようとしており、インターネット上の実用は想定しておりません。
 また、サーバー側プログラムを起動してから、クライアント側プログラムを起動致しましたし、表示されたファイアウォールの警告においても、許可をクリック致しました。

私の知識不足故、このような情報をあとから出すような羽目になり、申し訳ありませんでした。
■No31262に返信(金田武さんの記事)
> 表示されたファイアウォールの警告においても、許可をクリック致しました。

プログラムそのものは動作可能なコードであるように思います。

ファイアウォールでの許可が遅れたため、サーバーへの接続待ちが
タイムアウトしてしまい、例外が発生した可能性は無いでしょうか。


> 以下のソースコードを実行したところ、クライアントソフト側で、次の様なエラーが発生しました。

当方で試してみました。

サーバーアプリが待受け状態にない場合、クライアント側は
 「Dim tcp As New System.Net.Sockets.TcpClient(host, port)」
の行で、System.Net.Sockets.SocketException が発生しました。

アドレス表記が「[::1]:2001」ではなく「127.0.0.1:2001」だった事を除けば、
まったく同じエラーです。


一方、サーバー側で「listener.Start()」が実行された後であれば、
クライアントの「New TcpClient(host, port)」が成功しました。
「サーバーと接続しました。」と表示されまうし、その後の
文字列交換も正常に終了しています。(VB2010 on Win7)
魔界の仮面弁士様の環境において、成功された、という事で、問題はプログラムではなく、私のOS環境等によるものであると、思います。ファイアウォールの無効化や、実行ファイルの例外登録、ウイルスバスターの終了等を行いましたが、エラーが発生致しました。これにつきましては、今後の改善や、知人等に依頼し、他の環境における試験等を行いたいと思います。
 判断は微妙ですが、プログラムの正当性が確認されましたので、一応、解決済みとさせていただきます。皆様、知識不足の私のために、貴重なお時間を割いて、細切れの質問に答えて下さり、誠にありがとうございました。
解決済み!
■No31266に返信(金田武さんの記事)
>  魔界の仮面弁士様の環境において、成功された、という事で、問題はプログラムではなく、私のOS環境等によるものであると、思います。

念のための確認ですが、同じマシンでクライアントもサーバーも実行されているのですよね?
localhost と書かれていたのでその前提(同じマシン)でコードが問題なく動くかを魔界の仮面弁士さんも、私も試して成功していますが、その結果と合わないということなので、念のために書かせていただきました。


(localhost = 自分自身なので、違うマシンで実行しているとつながらない、エラー(例外)になります)
解決済み!
わざわざ解決済みのトピックに書き込んで下さり、ありがとうございました。
> 念のための確認ですが、同じマシンでクライアントもサーバーも実行されているのですよね?
はい。同じPCで両プログラムを実行しています。


以前ちょっとだけPHPをやっていた事があり、HTTP関連の事は知っていたつもりでしたが、やはり奥が深いですね。色々とご教授下さり、ありがとうございました。
  • 題名: Re[9]: VBでのリモート通信
  • 著者: 金田武
  • 日時: 2013/01/31 20:54:05
  • ID: 31298
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
■No31297に返信(金田武さんの記事)
> わざわざ解決済みのトピックに書き込んで下さり、ありがとうございました。
>>念のための確認ですが、同じマシンでクライアントもサーバーも実行されているのですよね?
> はい。同じPCで両プログラムを実行しています。
>
>
> 以前ちょっとだけPHPをやっていた事があり、HTTP関連の事は知っていたつもりでしたが、やはり奥が深いですね。色々とご教授下さり、ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板