TCP協議是TCP/IP協議簇中的傳輸層中的一個協議
也是TCP/IP協議簇最為重要的協議之一
在TCP/IP協議簇中
有一個協議和TCP協議非常類似
這就是UDP協議
網絡上進行基於UDP協議的數據傳送時
發送方只需知道接收方的IP地址(或主機名)和端口號就可以發送UDP數據包
而接收方只需知道發送方發送數據對應的端口號
就能夠接收UDP數據包了
傳送數據的雙方並不需要進行連接就能夠實現數據通訊
這樣就導致基於UDP協議的網絡應用程序
在傳送數據時無法保證可靠性
完整性和安全性
而TCP協議卻與之相反
TCP協議是一種面向連接的
並提供可靠的
完整的
安全的數據傳送的網絡協議
它提供可靠字節服務的協議
在網絡中通過TCP協議傳送數據之前
發送方和接收方之間必須建立連接
這種連接就是所謂的
握手
網絡中TCP應用
如同日常生活中的打電話
在通話之前
首先要撥號
震鈴(猶如發送方向接收方提出TCP連接申請
並等待TCP連接申請通過)
直到對方拿起電話時(發送方和接收方的TCP連接已經建立)
就可以通話了(傳送數據)
本文的主要內容就來介紹在Visual Basic
Net實現基於TCP協議網絡數據傳送的一種簡單的方法
一.簡介本文在實現TCP協議網絡應用時使用的類庫 Net FrameWork SDK中提供了很多用以實現TCP協議或與之相關協議的類庫
本文就選擇五個比較典型
也是比較簡單的類加以介紹
即
TcpListener類
TcpClient類
NetworkStream類
StreamReader類和StreamWriter類
TcpClient主要用以提出TCP連接申請
TcpListener主要用以偵聽端口號
並接收遠程主機的TCP連接申請
NetworkStream類是實現TCP數據傳輸的基礎數據流
StreamReader類作用是通過操作NetworkStream
實現從網絡接收數據
StreamWriter類作用是通過操作NetworkStream
實現向網絡傳輸數據
NetworkStream類
NetworkStream類主要是提供用於網絡訪問的基礎數據流
它主要是網絡數據傳輸的載體
並提供同步
異步方式來訪問網絡數據流
雖然NetworkStream類有構造函數
但在實際情況中更多是通過TcpClient實例的GetStream方法來初始化NetworkStream實例
以下就是使用TcpClient實例的GetStream方法來初始化NetworkStream實例具體代碼
Dim tcpClient As TcpClient
Dim nsStream As NetworkStream
tcpClient = New TcpClient(
)
對遠程主機的
端口提出TCP連接申請
nsStream = tcpClient
GetStream ( )
TCP連接建立後
獲得網絡數據傳輸的基礎數據流
在下面介紹的程序示例中
就是利用NetworkStream作為傳送和接收數據的載體
而操作這個載體的就是StreamWriter類和StreamReader類
表
和表
是NetworkStream類中一些常用的方法
屬性及其說明
方法
說明
BeginRead
開始異步讀者基礎數據流
BeginWrite
開始異步寫入基礎數據流
Close
關閉流並可選擇關閉基礎套接字
EndRead
結束異步讀取
EndWrite
結束異步寫入
Flush
刷新流中的數據
Read
從流中讀取數據
Seek
將流的當前位置設置為給定值
SetLength
設置流的長度
Write
將數據寫入流
表
NetworkStream類中常用的方法及其說明
其中
BeginRead
EndRead
和
BeginWrite
EndWrite
是二對異步方法
起作用分別相當於
Read
和
Write
方法
屬性
說明
CanRead
獲取當前流是否支持讀取
CanSeek
獲取流是否支持查找
該屬性總是返回 false
CanWrite
獲取當前流是否支持寫入
DataAvailable
獲取是否可以在流上讀取數據
Length
流上可用數據的長度
Position
獲取或設置流中的當前位置
表NetworkStream類中屬性及其說明
StreamReader類
StreamReader類能夠實現對基礎數據流的讀操作從而實現對經過基礎數據流傳送來的數據表是StreamReader類的常用的方法及其說明
方法
說明
Close
關閉StreamReader並釋放與閱讀器關聯的所有系統資源
DiscardBufferedData
允許StreamReader丟棄其當前數據
Peek
返回下一個可用的字符但不使用它
Read
讀取輸入流中的下一個字符或下一組字符
ReadBlock
從當前流中讀取最大數量的字符並從索引開始將該數據寫入緩沖區
ReadLine
從當前流中讀取一行字符並將數據作為字符串返回
ReadToEnd
從流的當前位置到末尾讀取流
表NetworkStream類中常用的方法及其說明
StreamWriter類
StreamWriter類能夠實現對基礎數據流的寫操作從而實現提供基礎數據流來傳送數據表是StreamWriter類的常用方法及其說明
方法
說明
Close
關閉當前的StreamWriter和基礎流
Flush
清理當前編寫器的所有緩沖區並使所有緩沖數據寫入基礎流
Write
寫入基礎數據流
WriteLine
寫入重載參數指定的某些數據後跟行結束符
表StreamWriter類的常用方法及其說明
TcpClient 類
TcpClient 類主要為TCP網絡服務提供客戶端連接TcpClient是類基於Socket類構建
它以更高的抽象程度提供TCP服務TcpClient 提供了通過網絡連接發送和接收數據的簡單方法表和表分別是TcpClient類常用方法屬性及其說明
方法
說明
Close
關閉 TCP 連接
Connect
使用指定的主機名和端口號將客戶端連接到 TCP主機
GetStream
返回用於發送和接收數據的流
表TcpClient類常用的方法
屬性
描述
LingerState
有關套接字逗留時間的信息
NoDelay
一個值該值在發送或接收緩沖區未滿時啟用延遲
ReceiveBufferSize
接收緩沖區的大小
ReceiveTimeout
TcpClient在啟動後為接收數據而等待的時間長度
SendBufferSize
發送緩沖區的大小
SendTimeout
在您啟動發送操作後TcpClient將為接收確認而等待的時間長度
表TcpClient類常用的屬性
TcpListener 類
TcpListener類的主要作用是從TCP網絡客戶端偵聽連接TcpListener類基於Socket 類
提供更高理念級別的TCP服務可以使用TcpListener從TCP客戶端偵聽連接像 FTP 和 HTTP 這樣的應用層協議是在 TcpListener 類的基礎上建立的表和表分別是TcpListener類常用方法屬性及其說明
方法
說明
AcceptSocket
接受掛起的連接請求
AcceptTcpClient
接受掛起的連接請求
Pending
確定是否有掛起的連接請求
Start
開始偵聽網絡請求
Stop
關閉偵聽器
表TcpListener 類常用的方法
屬性
說明
LocalEndpoint
獲取當前TcpListener的基礎EndPoint
Active
獲取一個值該值指示 TcpListener 是否正主動偵聽客戶端連接
Server
獲取基礎網絡Socket
表TcpListener 類常用的屬性
二.Visual Basic Net實現基於TCP協議數據傳送程序的體系結構
在下面介紹的用Visual Basic Net實現基於TCP協議的數據傳送程序是由二個子程序組成的也可以看成是服務器端程序和客戶端程序其中服務器端程序的功能是偵聽端口號接收遠程主要的TCP連接申請並接收遠程主機傳送來的文字數據另外一個子程序也就是所謂的客戶端程序主要實現向網絡的遠程主機提出TCP連接申請並在連接申請通過後向遠程主機傳送文字數據下面來詳細介紹Visual Basic Net實現TCP協議網絡數據傳送的服務器端程序和客戶端程序的具體步驟
三.服務器端程序的具體實現步驟
服務器端程序的實現關鍵在於偵聽端口號接收遠程主機的TCP連接申請獲得網絡數據傳輸的基礎數據流並通過基礎數據流接收數據接收數據使用的是StreamReader中ReadLine方法由於ReadLine方法是一個阻塞式的方法所以在下面具體的實現步驟中是接收數據是在創建的線程中完成的具體可參閱下面實現步驟中的第十一和十二步以下是Visual Basic Net實現TCP協議客戶端程序實現的具體步驟
啟動Visual Studio Net
選擇菜單【文件】|【新建】|【項目】後彈出【新建項目】對話框
將【項目類型】設置為【Visual Basic項目】
將【模板】設置為【Windows應用程序】
在【名稱】文本框中輸入【服務器端程序】
在【位置】的文本框中輸入【E:\VSNET項目】然後單擊【確定】按鈕這樣在E:\VSNET項目目錄中就產生了名稱為服務器端程序的文件夾並在裡面創建了名稱為服務器端程序的項目文件
把Visual Studio Net的當前窗口切換到【Formvb(設計)】窗口並從【工具箱】中的【Windows窗體組件】選項卡中往Form窗體中拖入下列組件並執行相應的操作
一個Label組件
一個StatusBar組件
一個ListBox組件
一個Button組件並在這個Button組件拖入Form的設計窗體後雙擊它則系統會在Formvb文件分別產生這個組件的Click事件對應的處理代碼
按照表所示調整窗體中各組件屬性的數值
組件類型
組件名稱
屬性
設置結果
Form
Form
Text
服務器端程序
Form
MaximizeBox
False
Form
FormBorderStyle
FixedSingle
Button
Button
Text
啟動服務
Button
FlatStyle
Flat
Label
Label
Text
服務尚未啟動
StatusBar
StatusBar
Text
無連接!
表【服務器端程序】項目中組件設定數值表
把Visual Studio Net的當前窗口切換到Formvb的代碼編輯窗口並在Formvb文件的最前面添加下列代碼下列代碼在Formvb中導入程序中要使用的類所在的命名空間
Imports SystemNetSockets
使用到TcpListen類
Imports SystemThreading
使用到線程
Imports SystemIO
使用到StreamReader類
在Formvb中創建各種可視組件的代碼中添加下列代碼下列代碼的作用是創建全局使用的實例和變量
Private iPort As Integer =
定義偵聽端口號
Private thThreadRead As Thread
創建線程用以偵聽端口號接收信息
Private tlTcpListen As TcpListener
偵聽端口號
Private blistener As Boolean = True
設定標示位判斷偵聽狀態
Private nsStream As NetworkStream
創建接收的基本數據流
Private srRead As StreamReader
從網絡基礎數據流中讀取數據
Private tcClient As TcpClient
在Formvb中的InitializeComponent過程之後添加下列代碼下列代碼的作用是定義Listen過程此過程的作用是偵聽本地機的端口號接受網絡主機的TCP連接申請並接收從建立申請的遠程主機發送來的文本數據
Private Sub Listen ( )
Try
tlTcpListen = New TcpListener ( iPort )
以端口號來初始化TcpListener實例
tlTcpListenStart ( )
開始監聽
StatusBarText = 正在監聽
tcClient = tlTcpListenAcceptTcpClient ( )
通過TCP連接請求
nsStream = tcClientGetStream ( )
獲取用以發送接收數據的網絡基礎數據流
srRead = New StreamReader ( nsStream )
以得到的網絡基礎數據流來初始化StreamReader實例
StatusBarText = 已經建立TCP連接!
循環偵聽
While blistener
Dim sMessage As String = srReadReadLine ( )
從網絡基礎數據流中讀取一行數據
If ( sMessage = STOP ) Then
tlTcpListenStop ( )
關閉偵聽
nsStreamClose ( )
srReadClose ( )
釋放資源
StatusBarText = 無連接!
thThreadReadAbort ( )
中止線程
Return
Else
判斷是否為斷開TCP連接控制碼
Dim sTime As String = DateTimeNowToShortTimeString ( )
獲取接收數據時的時間
ListBoxItemsAdd ( sTime + + sMessage )
End If
End While
Catch ex As SystemSecuritySecurityException
MessageBoxShow ( 偵聽失敗! 錯誤 )
End Try
End Sub
用下列代碼替換Formvb中的Button的Click事件對應的處理代碼下列代碼功能是用上面定義的Listen過程來初始化並啟動線程接收建立TCP連接的遠程主機發送來的文本數據
Private Sub Button_Click ( ByVal sender As SystemObject ByVal e As SystemEventArgs ) Handles ButtonClick
thThreadRead = New Thread ( New ThreadStart ( AddressOf Listen ) )
以Listen過程來初始化線程實例
thThreadReadStart ( )
啟動線程
ButtonEnabled = False
LabelText = 服務已經啟動!
LabelForeColor = ColorRed
End Sub
用下列代碼替換Formvb中的Dispose過程下面代碼的作用是重新定義Dispose過程在Dispose過程手動清除使用的資源回收垃圾
Protected Overloads Overrides Sub Dispose ( ByVal disposing As Boolean )
Try
thThreadReadAbort ( ) 中止線程
tlTcpListenStop ( ) 關閉偵聽
tcClientClose ( )
nsStreamClose ( )
srReadClose ( ) 釋放資源
Catch
End Try
If disposing Then
If Not ( components Is Nothing ) Then
componentsDispose ( )
End If
End If
MyBaseDispose ( disposing )
End Sub
至此在上述步驟都正確執行後【服務器端程序】項目的全部工作就完成了編譯生成可執行文件後接著介紹客戶端程序的實現步驟
四.客戶端端程序的具體實現步驟
客戶端端序的實現關鍵在於向網絡中的遠程主機提出TCP連接申請並在申請通過後得到傳輸數據的基礎數據流並通過對基礎數據流進行寫操作向遠程主機傳送文本數據
由於在客戶端程序中沒有使用阻塞式的方法所以程序中沒有使用到線程對遠程主機提出TCP連接申請的具體實現方法請參閱以下第步對基礎數據流進行寫操作從而實現向遠程主機傳送文本數據的方法請參閱以下第步下面客戶端程序的具體實現步驟
啟動Visual Studio Net
選擇菜單【文件】|【新建】|【項目】後彈出【新建項目】對話框
將【項目類型】設置為【Visual Basic項目】
將【模板】設置為【Windows應用程序】
在【名稱】文本框中輸入【客戶端程序】
在【位置】的文本框中輸入【E:\VSNET項目】然後單擊【確定】按鈕這樣在E:\VSNET項目目錄中就產生了名稱為客戶端程序的文件夾並在裡面創建了名稱為客戶端程序的項目文件
把Visual Studio Net的當前窗口切換到【Formvb(設計)】窗口並從【工具箱】中的【Windows窗體組件】選項卡中往Form窗體中拖入下列組件並執行相應的操作
二個Label組件
二個TextBox組件
一個StatusBar組件
二個Button組件並在這二個Button組件拖入Form的設計窗體後雙擊它們則系統會在Formvb文件分別產生這二個組件的Click事件對應的處理代碼
按照表所示調整窗體中各組件屬性的數值
組件類型
組件名稱
屬性
設置結果
Form
Form
Text
客戶端程序
Form
MaximizeBox
False
Form
FormBorderStyle
FixedSingle
Button
Button
Text
連接
Button
FlatStyle
Flat
Button
Text
發送
Button
FlatStyle
Flat
Label
Label
Text
服務器IP地址
Label
Text
信息
StatusBar
StatusBar
Text
無連接!
TextBox
TextBox
Text
TextBox
BorderStyle
FixedSingle
TextBox
Text
TextBox
BorderStyle
FixedSingle
表【客戶端程序】項目中組件設定數值表
把Visual Studio Net的當前窗口切換到Formvb的代碼編輯窗口並在Formvb文件的最前面添加下列代碼下列代碼在Formvb中導入程序中要使用的類所在的命名空間
Imports SystemNetSockets
使用到TcpListen類
Imports SystemIO
使用到StreamWriter類
Imports SystemNet
使用IPAddress類IPHostEntry類等
在Formvb中創建各種可視組件的代碼中添加下列代碼下列代碼的作用是創建全局使用的實例和變量
Private swWriter As StreamWriter
用以向網絡基礎數據流傳送數據
Private nsStream As NetworkStream
創建發送數據的網絡基礎數據流
Private tcpClient As TcpClient
通過它實現向遠程主機提出TCP連接申請
Private tcpConnect As Boolean = False
定義標識符用以表示TCP連接是否建立
用下列代碼替換Formvb中的Button的Click事件對應的處理代碼下列代碼功能是向遠程主機的端口號提出TCP連接申請並在連接建立後初始化基礎數據流
Private Sub Button_Click ( ByVal sender As SystemObject ByVal e As SystemEventArgs ) Handles ButtonClick
Dim ipRemote As IPAddress
Dim sHostName As String
Dim tcpClient As TcpClient
Try
ipRemote = IPAddressParse ( TextBoxText )
Catch
MessageBoxShow ( 輸入的IP地址不合法! 錯誤提示! )
Return
判斷給定的IP地址的合法性
End Try
Try
tcpClient = New TcpClient ( TextBoxText )
對遠程主機的端口提出TCP連接申請
nsStream = tcpClientGetStream ( )
通過申請並獲取傳送數據的網絡基礎數據流
swWriter = New StreamWriter ( nsStream )
使用獲取的網絡基礎數據流來初始化StreamWriter實例
ButtonEnabled = False
ButtonEnabled = True
tcpConnect = True
StatusBarText = 已經連接!
Catch
MessageBoxShow ( 無法和遠程主機端口建立連接! 錯誤提示! )
Return
End Try
End Sub
用下列代碼替換Formvb中的Button的Click事件對應的處理代碼下列代碼功能是對基礎數據流進行寫操作實現向遠程主機傳輸文本數據
Private Sub Button_Click ( ByVal sender As SystemObject ByVal e As SystemEventArgs ) Handles ButtonClick
If ( TextBoxText <> ) Then
swWriterWriteLine ( TextBoxText )
刷新當前數據流中的數據
swWriterFlush ( )
TextBoxText =
Else
MessageBoxShow ( 發送信息不能為空! 錯誤提示! )
End If
End Sub
用下列代碼替換Formvb中的Dispose過程下面代碼的作用是重新定義Dispose過程在過程中判斷TCP連接是否仍然建立如果建立則向遠程主機傳送控制碼斷開連接並手動清除使用的資源回收垃圾
Protected Overloads Overrides Sub Dispose ( ByVal disposing As Boolean )
If tcpConnect Then
swWriterWriteLine ( STOP )
發送控制碼
swWriterFlush ( )
刷新當前數據流中的數據
nsStreamClose ( )
swWriterClose ( )
清除資源 ( )
End If
If disposing Then
If Not ( components Is Nothing ) Then
componentsDispose ( )
End If
End If
MyBaseDispose ( disposing )
End Sub
至此【客戶端程序】就完成了在正確編譯項目後就可以選擇局域網中任二台計算機來測試了一台運行客戶端程序一台運行服務器端程序在服務器端程序運行後單擊【啟動服務】按鈕啟動服務後在客戶端程序的【服務器IP地址】文本框中輸入網絡中運行服務器端程序主機對應的IP地址後單擊【連接】按鈕就和啟動服務的服務器端程序建立TCP連接此時就可以在客戶端程序的【信息】文本框中輸入文本信息後單擊【發送】按鈕就能夠把文本信息傳送到服務器端了圖和圖分別是客戶端程序和服務器端程序運行後進行通訊時的界面
五.總結
雖然本文用Visual Basic Net實現一個簡單的基於TCP協議的網絡應用程序但程序中使用的是NetworkStream作為載體通過StreamWriter和StreamReader通過操作這個載體從而實現數據傳輸和接收這種實現TCP協議方法雖然比較簡單但卻無法回避NetworkStream作為網絡傳輸接收數據載體的一個致命的缺陷那就是NetworkStream只能傳輸基於文本類型的數據如果要傳輸基於字節的數據使用這種方法就勉為其難了而套接字(Socket)就能夠勝任這項工作套接字不僅能夠實現各種類型數據在網絡上的傳輸和接收也是實現網絡中其他應用協議的關鍵諸位若想真正成為網絡編程的高手必須掌握Socket的使用方法最後希望本文能夠開啟您編寫網絡應用程序之門對您掌握更深層次網絡編程有所幫助
From:http://tw.wingwit.com/Article/program/net/201311/13184.html