ソケット通信を実装する方法について
サンプル コードのダウンロード (vbmigtips_Socket.exe, 122 KB)
ソケットを使用してプロセス間および、マシン間での通信を行いたい場合があると思います。そこで今回は、ソケットを使用してアプリケーション間を TCP 通信し、データの送受信を行う方法について紹介します。
Visual Basic 6.0 では、Winsock コントロールを使用してソケット通信を実現します。[プロジェクト]メニューの[コンポーネント]を選択し、「コンポーネント」ダイアログを表示します。ダイアログの[コントロール]タブで「Microsoft Winsock Control 6.0」のチェックボックスをオンにして、[OK]ボタンを選択します。すると、Winsock コントロールが追加されます。
まず、リモートホスト (サーバー) 側のアプリケーション (図1) を作成します。
図1
Form に Winsock コントロールを貼り付けます。実装コードは以下のとおりです。
Private Sub Command1_Click()
Winsock(0).LocalPort = "1111"
Winsock(0).Listen
Command1.Enabled = False
Command2.Enabled = True
End Sub
Private Sub Command2_Click()
Dim iintLoop As Integer
For iintLoop = 0 To intConnectMax
Winsock(iintLoop).Close
Next
Command1.Enabled = True
Command2.Enabled = False
End Sub
Private Sub Winsock_ConnectionRequest(Index As Integer, ByVal requestID As Long)
intConnectMax = intConnectMax + 1
Winsock(intConnectMax).Accept requestID
End Sub
Private Sub Winsock_DataArrival(Index As Integer, ByVal bytesTotal As Long)
Dim strBuf As String
Winsock(Index).GetData strBuf
Text1.Text = "クライアントから「" & strBuf & "」を受信しました。"
Winsock(Index).SendData StrConv(strBuf, vbWide)
End Sub
|
リスト1
上記 (リスト1) の「Winsock(0).LocalPort = "1111"」でポート番号を指定し、「Winsock(0).Listen」で相手アプリケーションから接続要求を待ちます。接続要求が来ると ConnectionRequest イベントが発生します。ConnectionRequest イベントでは、相手アプリからの接続要求を受け付けます。また、相手のアプリケーション (クライアント) からデータが送信されてきたときに発生する DataArrival イベントで、受信されたデータをテキストボックスに表示し、クライアントにデータを返信します。「Winsock(Index).GetData strBuf」でクライアントから送信されてきたデータを取得し、「Text1.Text = "クライアントから「" & strBuf & "」を受信しました。" 」でテキストに表示します。「Winsock(Index).SendData StrConv(strBuf, vbWide)」でクライアントにデータを返信します。
続いて、クライアント側のアプリケーション (図2) を作成します。
図2
クライアント側のアプリケーション (図2) は、Form を Load 時にリモートホスト側に接続し、[送信]ボタンを選択すると、テキストボックス内のデータを上記で作成したリモートホスト側のアプリケーションに送信されます。そして、リモートホスト側から返信が帰ってきます。こちらも Form に Winsock コントロールを貼り付けます。クライアント側の実装コードは以下のとおりです。
Private Sub Form_Load()
Winsock1.LocalPort = 0
Winsock1.RemoteHost = "localhost"
Winsock1.RemotePort = "1111"
Winsock1.Connect
End Sub
Private Sub Command1_Click()
Winsock1.SendData Text1.Text + vbCrLf
End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Dim strBuf As String
Winsock1.GetData strBuf
Text2.Text = "リモートホストから「" & strBuf & " 」を受信しました。"
End Sub
|
リスト2
上記 (リスト2) の「Winsock1.LocalPort = 0」では、一度使ったローカルポートを再使用するときにエラーが発生するため O クリアします。「Winsock1.RemoteHost = "localhost"」「Winsock1.RemotePort = "1111"」でサーバーマシンのホスト名とサーバーアプリケーションに対応するポート番号を指定します。そして「Winsock1.Connect」でコネクションの接続要求を送信します。
「Winsock1.SendData Text1.Text + vbCrLf」で textBox1 のデータをサーバーに送信します。 DataArrival イベントの「Winsock1.GetData strBuf」ではサーバーから受信されてきたデータを取得し、「Text2.Text = "リモートホストから「" & strBuf & " 」を受信しました。"」でテキストボックスに表示します。
リスト1 とリスト2 を実装し、実行してみましょう。まず、クライアント側のアプリケーション (リスト1) を実行し、[接続]ボタンを選択します (図1)。次に、クライアント側のアプリケーション (リスト2) を実行します (図2)。これにより、リモートホスト側とクライアント側のアプリケーションが接続されます。図2 のテキストボックスにデータを入力し、[送信]ボタンを選択すると、入力したデータがリモートホスト側に送信され、テキストボックスのデータを表示します (図3)。
図3
テキストに受信されたデータを表示後、受信されたデータをクライアント側に送信します。すると、データを受信したクライアント側は、テキストボックスに受信されたデータを表示します (図4)。
図4
このように、Visual Basic 6.0 では Winsock コントロールを使用しました。一方、Visual Basic .NET では System.Net.Sockets 名前空間を使用して実装します。そこで続いては、Visual Basic .NET での実装方法について紹介します。
まず、リモートホスト (サーバー) 側のアプリケーションを作成します。実装コードは以下のとおりです。
Private intPortNo As Integer = 1111
Private objTcpListener As New System.Net.Sockets.TcpListener(intPortNo)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles Button1.Click
objTcpListener.Start()
Button1.Enabled = False
Button2.Enabled = True
Timer1.Start()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles Button2.Click
objTcpListener.Stop()
Button1.Enabled = True
Button2.Enabled = False
Timer1.Stop()
End Sub
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim bytReceiveBuffer(255) As Byte
Dim bytSendBuffer() As Byte
Dim intReceiveLength As Integer
Dim objNetworkStream As System.Net.Sockets.NetworkStream
Dim objTcpClient As System.Net.Sockets.TcpClient
Dim strReceivedData As String
With objTcpListener
If .Pending = False Then
Exit Sub
End If
objTcpClient = .AcceptTcpClient
With objTcpClient
objNetworkStream = .GetStream
With objNetworkStream
Do
If .DataAvailable = True Then
intReceiveLength = .Read(bytReceiveBuffer, 0, bytReceiveBuffer.Length)
strReceivedData &= System.Text.Encoding.Default.GetString(bytReceiveBuffer).
Substring(0, intReceiveLength)
ElseIf Not strReceivedData Is Nothing Then
TextBox1.Text = "クライアントから「" & strReceivedData & "」受信しました。"
bytSendBuffer = System.Text.Encoding.Default.GetBytes(strReceivedData)
.Write(bytSendBuffer, 0, bytSendBuffer.Length)
Exit Do
End If
Loop
End With
.Close()
End With
End With
End Sub
|
リスト3
上記 (リスト3) の「objTcpListener.Start()」で TCP の受信接続の待機を開始し、「Timer1.Start()」でタイマをスタートさせます。「objTcpListener.Stop()」でリスナを閉じ、「Timer1.Stop()」でタイマを止めます。
「If .Pending = False Then ... End If」では、待機中に接続要求が無かった場合、プロシージャを抜けます。「objTcpClient = .AcceptTcpClient」では、データの送受信に使用できる TCP クライアントを取得し、「objNetworkStream = .GetStream」でデータを送受信するために使用するストリームを取得します。「strReceivedData &= System.Text.Encoding.Default.GetString(bytReceiveBuffer).Substring(0, intReceiveLength)」で TCP クライアントから送信されたデータを取得し、「bytSendBuffer = System.Text.Encoding.Default.GetBytes(strReceivedData)」で String に変換します。読み取ったデータは「TextBox1.Text = "クライアントから「" & strReceivedData & "」受信しました。"」でテキストボックスに表示します。そして、「bytSendBuffer = System.Text.Encoding.Default.GetBytes(strReceivedData)」で Bytes の配列に変換し、そのデータを「.Write(bytSendBuffer, 0, bytSendBuffer.Length)」で TCP クライアントに返信します。最後に「.Close()」で TCP 接続を終了します。
続いて、クライアント側のアプリケーションを作成します。実装コードは以下のとおりです。
Private intPortNo As Integer = 1111
Private objNetStream As System.Net.Sockets.NetworkStream
Private objTcpClient As System.Net.Sockets.TcpClient
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles Button1.Click
Dim bytReceiveBuffer(255) As Byte
Dim bytSendBuffer As Byte()
Dim intDataLength As Integer
Dim strReceivedData As String
objTcpClient = New System.Net.Sockets.TcpClient
With objTcpClient
Try
objTcpClient.Connect("localhost", intPortNo)
objNetStream = .GetStream
With objNetStrea
bytSendBuffer = System.Text.Encoding.Default.GetBytes(TextBox1.Text)
.Write(bytSendBuffer, 0, bytSendBuffer.Length)
Do
If .DataAvailable Then
intDataLength = .Read(bytReceiveBuffer, 0, bytReceiveBuffer.Length)
strReceivedData &= System.Text.Encoding.Default.GetString(bytReceiveBuffer).
Substring(0, intDataLength)
ElseIf Not strReceivedData Is Nothing Then
TextBox2.Text = "リモートホストから「" & strReceivedData & " 」を受信しました。"
Exit Do
End If
Loop
End With
Catch Ex As Exception
MsgBox(Ex.Message)
End Try
.Close()
End With
End Sub
|
リスト4
上記 (リスト4) の「objTcpClient.Connect("localhost", intPortNo)」でリモートホストと接続します。「bytSendBuffer = System.Text.Encoding.Default.GetBytes(TextBox1.Text)」でデータをリモートホストへ送信します。リスト4 の「Do ... Loop」でリモートホストからの返信を受信します。受信されたデータは「TextBox2.Text = "リモートホストから「" & strReceivedData & " 」を受信しました。"」でテキストボックスに表示します。最後に「.Close()」で TCP 接続を終了します。
リスト3 とリスト4 を実装し、実行してみましょう。まず、クライアント側のアプリケーション (リスト1) を実行し、[接続]ボタンを選択します (図1)。次に、クライアント側のアプリケーション (リスト2) を実行します (図2)。これにより、リモートホスト側とクライアント側のアプリケーションが接続されます。図2 のテキストボックスにデータを入力し、[送信]ボタンを選択すると、入力したデータがリモートホスト側に送信され、テキストボックスのデータを表示します (図3)。テキストに受信されたデータを表示後、受信されたデータをクライアント側に送信します。すると、データを受信したクライアント側は、テキストボックスに受信されたデータを表示します (図4)。