画像ファイル
画像ファイル   C#、Vb2005 でSocket通信
VB2005のコード
VB2005のコード
Option Strict On
Imports System.Text
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading
Imports System.IO
Public Class Form1

' //***********************************************************
' //初期設定宣言
' //***********************************************************
' //受信は必ずshift-jisと仮定している
' //他の文字の場合はここを変える事
Dim ecUni As Encoding = Encoding.GetEncoding("utf-16")
Dim ecSjis As Encoding = Encoding.GetEncoding("shift-jis")

'//サーバー設定
Dim server As TcpClient = Nothing
'//サーバーのリスナー設定
Dim listener As TcpListener = Nothing
'//サーバーのセカンドスレッドの設定
Dim threadServer As Thread = Nothing

'//クライアント設定
Dim client As TcpClient = Nothing
'//クライアントのセカンドスレッドの設定
Dim threadClient As Thread = Nothing


'//**********************************************************
'//デリゲート宣言
'//**********************************************************
'//別スレッドからメインスレッドのテキストボックスに書き込むデリゲート
Delegate Sub dlgWriteText(ByVal text As String)

'//引数を持たない汎用のデリゲート
'//ストップボタンを押す等に使用
Delegate Sub dlgMydelegate()

'//***********************************************************
'//ソケット通信の開始処理
'//***********************************************************
'//Startボタン押下
Private Sub butStart_Click(ByVal sender As Object, ByVal e As EventArgs) Handles butStart.Click
StartSock()
End Sub
'//ソケット通信開始
Private Sub StartSock()
'//チェックボックスを見て
'//サーバー又はクライアントスタート
Dim OpenFlg As Boolean
If radioServer.Checked Then
OpenFlg = ServerStart()
picIndicator.BackColor = Color.Green
Else
OpenFlg = ClientStart()
End If
'//ボタンのenableを変える
If OpenFlg Then
butStart.Enabled = False
butStop.Enabled = True
End If
End Sub

'//***********************************************************
'//セカンドスレッドの作成とサーバーのスタート
'//***********************************************************
Private Function ServerStart() As Boolean
'//TcpListenerを使用してサーバーの接続の確立
Try

'//lisenerが無い場合
If listener Is Nothing Then
listener = New TcpListener(IPAddress.Any, Int32.Parse(textBoxPortNo.Text))
End If
'//クライアント接続要求の受付開始
listener.Start()

'//ログの書き込み
writeLog("サーバを開始しました。")

'//スレッドの作成と開始
threadServer = New Thread(New ThreadStart(AddressOf ServerListen))
threadServer.Start()
Return True

Catch ex As Exception
'//エラーが起きた
writeLog("サーバ接続エラー:" + ex.Message.ToString())
listener.Stop()
picIndicator.BackColor = Color.Navy
Return False
End Try
End Function


'//***********************************************************
'//別スレッドで実行されるサーバ側の処理
'//***********************************************************
Private Sub ServerListen()


'//クライアントの要求があったら、接続を確立する
'//クライアントの要求が有るまでここで待機する
server = listener.AcceptTcpClient()

'//ログの書き込みをデリゲートで実行
Me.textBoxLog.BeginInvoke(New dlgWriteText(AddressOf writeLog) _
, New Object() {"クライアントが接続しました。"})

'//インジケータの色を変える
'//バックカラーの変更はデリゲートの必要は無し
picIndicator.BackColor = Color.LightGreen

'//クライアントとの間の通信に使用するストリームを取得
Dim stream As NetworkStream = server.GetStream()

'//受信文字が入る。
'//この数字は少なくても可、少ない場合はLoopが何回か実行される
Dim bytes(1000) As Byte

'//受信文字を書き込むデリゲートを作成。
Dim dlgText As dlgWriteText = New dlgWriteText(AddressOf WriteReadText)

While (True)

Try

'//受信が無い場合はここで待機する
'//文字受信が有った場合とクライアントが接続を切った場合に
'//次のステップに進む
Dim intCount As Integer = stream.Read(bytes, 0, bytes.Length)

If intCount <> 0 Then

'//intStrCountが0より大きい場合は文字受信有り

'//受信部分だけ切り出す
Dim getByte(intCount - 1) As Byte
For i As Integer = 0 To intCount - 1
getByte(i) = bytes(i)
Next
Dim uniBytes() As Byte
'//'S-Jisからユニコードに変換
uniBytes = Encoding.Convert(ecSjis, ecUni, getByte)

'//バイト配列から文字列に変換する
Dim strGetText As String = ecUni.GetString(uniBytes)

'//メインスレッドのテキストボックスに書き込む
textBoxWrite.Invoke(dlgText, strGetText)
Else
'//intStrCount=0の場合はクライアントが接続を切った
'//デリゲートからログを書き込む
Me.textBoxLog.BeginInvoke(New dlgWriteText(AddressOf writeLog) _
, New Object() {"クライアントが切断されました。"})

'//サーバの切断と再接続がタイマーを使用して行なわれる
'//タイマーはデリゲートで呼ばれる
Me.BeginInvoke(New dlgMydelegate(AddressOf setStartTimer) _
, New Object() {})

'//ループを抜ける
Return

End If

Catch e As ThreadAbortException

'//Stopボタンを押すとこのスレッドが削除されこのエラーが起きる。
'//それを回避する為のエラー処理。
'//切断されたのでループを抜ける
Return

Catch ex As Exception
'//切断で起こるスレッドエラー以外のエラーはここに来る
Me.textBoxLog.BeginInvoke(New dlgWriteText(AddressOf writeLog) _
, New Object() {"受信エラー  " + ex.Message.ToString()})
Me.butStart.BeginInvoke(New dlgMydelegate(AddressOf StartSock) _
, New Object() {})
'//ループを抜ける
Return
End Try
End While
End Sub

'//***********************************************************
'//セカンドスレッドの作成とクライアントのスタート
'//***********************************************************
Private Function ClientStart() As Boolean
Try
'//クライアントのソケットを用意
client = New TcpClient(textBoxIp.Text, Int32.Parse(textBoxPortNo.Text))

'//サーバからのデータを受信するループをスレッドで処理
threadClient = New Thread(New ThreadStart(AddressOf ClientListen))
threadClient.Start()

'//接続インディケータ
picIndicator.BackColor = Color.LightGreen
writeLog("クライアント接続接続されました:")
Return True
Catch ex As Exception
writeLog("クライアント接続エラー:" + ex.Message.ToString())
picIndicator.BackColor = Color.Navy
Return False
End Try
End Function


'//***********************************************************
'//別スレッドで実行されるクライアント側の処理
'//ここの処理はServerと同じなのでそちらを参照のこと
'//***********************************************************
Private Sub ClientListen()
Dim stream As NetworkStream = client.GetStream()

Dim bytes(1000) As Byte
Dim dlgText As dlgWriteText = New dlgWriteText(AddressOf WriteReadText)

While (True)
Try
Dim intCount As Int32 = stream.Read(bytes, 0, bytes.Length)
If intCount <> 0 Then

'//受信部分だけ切り出す
Dim getByte(intCount - 1) As Byte
For i As Integer = 0 To intCount - 1
getByte(i) = bytes(i)
Next
Dim uniBytes() As Byte
'//'S-Jisからユニコードに変換
uniBytes = Encoding.Convert(ecSjis, ecUni, bytes)
Dim strGetText As String = ecUni.GetString(uniBytes)
textBoxWrite.Invoke(dlgText, strGetText)
Else
'//サーバーが切断された
Me.textBoxLog.BeginInvoke(New dlgWriteText(AddressOf writeLog) _
, New Object() {"ホストが切断されました。"})
Me.butStart.BeginInvoke(New dlgMydelegate(AddressOf StopSock) _
, New Object() {})
Return
End If
Catch e As ThreadAbortException
'//何もしません
Return

Catch ex As Exception
Me.textBoxLog.BeginInvoke(New dlgWriteText(AddressOf writeLog) _
, New Object() {"受信エラー  " + ex.ToString()})
Return
End Try
End While
End Sub

'//***********************************************************
'//ソケット通信の終了処理
'//***********************************************************
'//Stopボタン押下
Private Sub butStop_Click(ByVal sender As Object, ByVal e As EventArgs) Handles butStop.Click
StopSock()
End Sub
Private Sub StopSock()
'//チェックボックスを見て
'//サーバー又はクライアントストップ
If (radioServer.Checked) Then
CloseServer()
Else
CloseClient()
'//ボタンのenableを変える
End If
butStart.Enabled = True
butStop.Enabled = False

End Sub

'//サーバーのクローズ
Private Sub CloseServer()
'//サーバーのインスタンスが有って、接続されていたら
If server IsNot Nothing AndAlso server.Connected Then
server.Close()
End If
'//スレッドは必ず終了させること
If threadServer IsNot Nothing Then
threadServer.Abort()
End If
'//インディケータの色を変える
picIndicator.BackColor = Color.Navy
'//ログを書き込む
writeLog("サーバーが閉じられました。")
End Sub

'//クライアントのクローズ
Private Sub CloseClient()
'//クライアントのインスタンスが有って、接続されていたら
If client IsNot Nothing AndAlso client.Connected Then
client.Close()
End If
'//スレッドは必ず終了させること
If threadClient IsNot Nothing Then
threadClient.Abort()

'//インディケータの色を変える
picIndicator.BackColor = Color.Navy
'//ログを書き込む
writeLog("クライアントが閉じられました。")
End If
End Sub



'//******************************************************
'//デリゲートから呼ばれるテキストに書き込むメソド、
'//*******************************************************
'//受信文字をテキストボックスに書き込む
Private Sub WriteReadText(ByVal text As String)
'//受信文字の改行は全て↓に置き換えられる
text = text.Replace(Environment.NewLine, "↓")
Me.textBoxRead.AppendText(text + Environment.NewLine)
End Sub

'//Logを書き込む
Private Sub writeLog(ByVal strlog As String)
Me.textBoxLog.AppendText(DateTime.Now.ToString() + " " _
+ strlog + Environment.NewLine)
End Sub


'//************************************************************
'//文字データの送信
'//************************************************************
'//送信ボタン押下
Private Sub butSend_Click(ByVal sender As Object, ByVal e As EventArgs) Handles butSend.Click
SendStringData()
End Sub

'//文字データーの送信
Private Sub SendStringData()
'//sift-jisに変換して送る
Dim data() As Byte = ecSjis.GetBytes(textBoxWrite.Text)
'//送信streamを作成
Dim stream As NetworkStream = Nothing
Try
'//サーバーとクライアントを分けて送信
If radioClient.Checked Then
stream = client.GetStream()
Else
stream = server.GetStream()
End If
'//Streamを使って送信
stream.Write(data, 0, data.Length)
Catch
MessageBox.Show("送信できませんでした。", "送信エラー")
writeLog("送信エラー:送信できませんでした。")
End Try
End Sub
'//******************************************************
'//別スレッドから抜けて、メインスレッドからStart Stopを
'//実行するタイマー
'//******************************************************
'//デリゲートから呼ばれタイマーをスタートします
Private Sub setStartTimer()
timerServerStart.Enabled = True
End Sub

'//通信相手のクライアントが接続を切った時に
'//別スレッドからデリゲートを通して呼ばる
Private Sub timerServerStart_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles TimerServerStart.Tick
timerServerStart.Enabled = False
StopSock()
'//サーバーを再スタートします
StartSock()
End Sub


'//******************************************************
'//テキストボックスのクリア
'//******************************************************
Private Sub butCls_Click(ByVal sender As Object, ByVal e As EventArgs) Handles butClsWrite.Click
textBoxWrite.Clear()
End Sub
Private Sub butClsRead_Click(ByVal sender As Object, ByVal e As EventArgs) Handles butClsRead.Click

textBoxRead.Clear()
End Sub
Private Sub butClsLog_Click(ByVal sender As Object, ByVal e As EventArgs) Handles butClsLog.Click
textBoxLog.Clear()
End Sub

'//*******************************************************
'//プログラムの終了処理
'//*******************************************************
Private Sub FomSoch_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs)
CloseServer()
CloseClient()
End Sub

End Class


画像 上記VB2005のコードのダウンロード

C#、Vb2005 でSocket通信 本文に戻る   


画像ファイル