第三章 資料的傳收與接送 3-1 TCP程式設計 3-2 UDP程式設計 3-3 Socket程式設計 3-4資料的非同步傳送與接收
第三章 資料的傳收與接送 3-1 TCP程式設計
TCP/IP網路程式的架構
建立伺服端與接收資料 '建立TcpListener類別 TcpListener = New TcpListener (IPAddress類別,通訊埠) MyTcpListener.Start() '接受客戶端的TcpClient服務 Dim TcpClient As TcpClient = MyTcpListener.AcceptTcpClient() '取得來自客戶端的IP Address Dim clientIP As IPAddress = IPAddress.Parse( CType(MyTcpListener.LocalEndpoint, _ IPEndPoint).Address.ToString()) '取得客戶端的TcpClient所傳送的資料 Dim ns As NetworkStream = MyTcpClient.GetStream Dim data(MyTcpClient.ReceiveBufferSize) As Byte '讀入傳進的資料的長度 Dim BytesRead As Integer = ns.Read(data, 0 , CInt( MyTcpClient.ReceiveBufferSize)) '將Byte型態轉換為String 接收資料=Encoding.Default.GetString(data, 0, BytesRead))
連接至伺服端與傳送資料 '連接至伺服端 TcpClient.Connect(IP位址, 通訊埠) '使用NetworkStream類別來接收與傳送資料 Dim ns As NetworkStream = TcpClient.GetStream '使用預設的編碼方式來將傳送資料編碼 Dim data As Byte() = Encoding.Default.GetBytes(要傳送的資料封包) '傳送資料 ns.Write(data, 0, data.Length)
SocketException類別 SocketErrorCode: 僅陳述當時網路環境的狀況,並不全然是程式所造成的錯誤。 說明屬於哪一種型態的錯誤,讓程式設計師來判斷發生錯誤的原因,並做進一步的處理。 僅陳述當時網路環境的狀況,並不全然是程式所造成的錯誤。
Encoding類別 替資料流位元組進行編碼 純英文可用ASCII方式編碼 欲顯示中文可採用Default方式編碼 ASCII BigEndianUnicode 取得UTF-16格式的編碼方式,它是以位元組由大到小位元組順序來排列。 Default 取得目前作業系統的編碼方式。 Unicode 取得UTF-16格式的編碼方式,它是以位元組由小到大位元組順序來排列。 UTF32 取得UTF-32格式的編碼方式,它是以位元組由小到大位元組順序來排列。 UTF7 取得UTF-7格式的編碼方式。 UTF8 取得UTF-8格式的編碼方式。
Thread(執行緒) 宣告Thread物件 (eg. 程式3-1-1) 產生Thread物件 啟動Thread物件 Thread副程式名稱 Dim tcpThread As Thread 產生Thread物件 tcpThread = New Thread(New ThreadStart(AddressOf StartTcpListener)) 啟動Thread物件 tcpThread.Start( ) Thread副程式名稱 Public Sub StartTcpListener( )
NetworkStream:非同步讀取資料 BeginRead方法。 TcpClient.GetStream.BeginRead(接收的資料, 開始讀取位置, 讀取長度, AddressOf 指派程序, Nothing) clientTCP.GetStream.BeginRead( data, 0, _ CInt(clientTCP.ReceiveBufferSize), _ AddressOf ReceiveMessage, Nothing) 會在 BeginRead 完成時加以執行
NetworkStream:停止非同步讀取 EndRead方法。 資料長度=TcpClientTCP.GetStream.EndRead( IAsyncResult) 讀取資料=Encoding.Default.GetString(接收資料, 開始位置, 資料長度) 範例: 3-1-4 放入本身read callback function所傳入之 參數
NetworkStream程式碼範例 使用指派者執行緒(上一層)的Subroutine (範例: 3-1-4) Me.Invoke(New 指派程序宣告名稱(AddressOf Me.程序名稱), 參數) '指派程序宣告 Public Delegate Sub 指派程序宣告名稱(參數) Public Sub 程序名稱(參數) '要處理的事 End Sub
第三章 資料的傳收與接送 3-2 UDP程式設計
UdpClient類別 定義在System.Net.Sockets的命名空間。 為一個不可靠的傳輸協定: 傳送資料後,並不會去確認對方是否有收到完整的資料。 接收資料的客戶端,也不會去考慮所收到的資料是否正確?完整?重覆接收?
建立UdpClient類別 '僅初始化UdpClient Dim udpClient As New UdpClient() '連接至本機通訊埠 Dim udpClient As New UdpClient(通訊埠) '連接至本機 Dim udpClient As New UdpClient(AddressFamily家族) '連接至指定IP與通訊埠 Dim udpClient As New UdpClient(IPEndPoint類別) Dim udpClient As New UdpClient(通訊埠, AddressFamily家族) '連接至指定主機名稱與通訊埠 Dim udpClient As New UdpClient(主機名稱, 通訊埠)
UdpClient連接至伺服器 '連接至指定IP與通訊埠 UdpClient.Connect(IPEndPoint類別) UdpClient.Connect(IPAddress類別, 通訊埠) '連接至指定主機名稱與通訊埠 UdpClient.Connect(主機名稱, 通訊埠)
UdpClient傳送資料至伺服器 '已連接至伺服器 UdpClient.Send(傳送資料位元組陣列, 傳送資料的長度) '尚未連接至伺服器 UdpClient.Send(傳送資料位元組陣列, 傳送資料的長度, IPEndPoint類別) UdpClient.Send(傳送資料位元組陣列, 傳送資料的長度, 主機名稱, 通訊埠)
UdpClient接收伺服器的資料 UdpClient.Receive(伺服器的IPEndPoint類別) 關閉UdpClient通訊 UdpClient.Close()
接收端與發送端的通訊埠與IP位址
第三章 資料的傳收與接送 3-3 SOCKET程式設計
Socket應用程式的架構
Socket程式的作業流程
Socket 命名空間: System.Net.Sockets Socket 類別針對網路通訊提供了一系列豐富的方法和屬性 Socket 類別可以讓您使用ProtocolType 列舉型別中列出的任何通訊協定來執行同步的和非同步的 (Asynchronous) 資料傳送。
Socket Socket 類別遵循 .NET Framework 的非同步方法命名模式。例如,同步Receive 方法對應於非同步BeginReceive 和 EndReceive 方法。 如果您正在撰寫相當簡單的應用程式,而且不需要最大效能,請考慮使用TcpClient、TcpListener 和 UdpClient。這些類別會提供 Socket 通訊較為簡單且更易於使用的介面
同步作業模式--TCP 伺服器可以使用Listen 方法來聆聽連接 Accept 方法會處理任何輸入的連接要求,並傳回可以用來與遠端主機進行資料傳遞的 Socket 使用這個傳回的 Socket 來呼叫Send 或 Receive 方法 如果您要指定本機 IP 位址和通訊埠編號,請在呼叫Listen 方法之前呼叫Bind 方法
同步作業模式--TCP 如果您要基礎服務提供者為您指派可用的通訊埠,請使用編號為零的通訊埠 如果您要連接至接聽主機,請呼叫Connect 方法。 若要進行資料傳遞,請呼叫Send 或 Receive 方法。
同步作業模式--UDP 不需要聆聽連接 呼叫 ReceiveFrom方法以接受任何輸入的資料包 (Datagram) 使用 SendTo 方法以傳送資料包至遠端主機
建立Socket類別 DIM SocketServer AS New Socket(通訊協定家族, 通訊端類型, 通訊協定) DIM SocketServer AS = New Socket( _ AddressFamily.InterNetwork, _ SocketType.Stream, ProtocolType.Tcp)
將IP位址、通訊埠與Socket物件繫結 Dim ep As New IPEndPoint(IPAddress.Parse(IP位址), 通訊埠) SocketServer.Bind(ep) Dim ep As New IPEndPoint( IPAddress.Parse("127.0.0.1"), 5001)
開啟Socket物件的接聽功能 SocketServer.Listen(最大連接數) SocketServer. Listen(9)
建立客戶端Socket物件 DIM SocketClient AS New Socket(通訊協定家族, 通訊端類型, 通訊協定) Dim ep As New IPEndPoint(IPAddress.Parse(IP位址), 通訊埠) SocketClient.Connect(ep) DIM SocketClient AS New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) Dim ep As New IPEndPoint(IPAddress.Parse("127.0.0.1"), 5001)
伺服端Socket接受客戶端Socket連接 Dim SocketClient As Socket SocketClient = SocketServer.Accept()
Socket類別傳送資料 SocketClient.Send(Encoding.Default.GetBytes("傳送資料"))
Socket類別接收資料 Dim RecvLength As Integer Dim RecvStr As String RecvLength = SocketClient.Receive(data) If RecvLength > 0 Then RecvStr = Encoding.Default.GetString(data).Trim End If
關閉已開啟的Socket通訊 SocketServer.Close 暫停通訊 Shutdown Receive 暫停接收資料。 Send 暫停傳送資料。 Both 暫停接收和傳送資料。
第三章 資料的傳收與接送 3-4資料的非同步傳送與接收
非同步作業模式 --TCP 使用 Socket、BeginConnect 和 EndConnect 方法來與接聽主機進行連接 使用 BeginSend 和 EndSend,BeginReceive 和 EndReceive 方法,以非同步方式進行資料傳遞 輸入的連接要求可以使用BeginAccept 和 EndAccept 加以處理
非同步作業模式 --UDP 使用BeginSendTo 和 EndSendTo 傳送資料包 使用BeginReceiveFrom 和 EndReceiveFrom 接收資料包
非同步作業模式 如果在一個通訊端上執行多個非同步的作業,這些作業不一定會依照所啟動的順序完成 完成傳送和接收資料時,請使用Shutdown 方法來停用 Socket 呼叫 Shutdown 之後,要呼叫Close 方法來釋放與 Socket 相關的所有資源。
Socket類別非同步接受連接 '建立委派 Accept = New AsyncCallback(AddressOf OnAccept) '開始準備接收客戶端Socket連接 SocketServer.BeginAccept(Accept, SocketServer) Public Sub OnAccept(ByVal ar As IAsyncResult) '接受客戶端連入 SocketClient = SocketServer.EndAccept(ar) End Sub
Socket類別非同步接收資料 '建立委派 ReceiveData = New AsyncCallback(AddressOf OnReceive) '開始接受客戶端Socket傳送資料 SocketClient.BeginReceive(data, 0, data.Length, SocketFlags.None, _ ReceiveData, SocketClient) Public Sub OnReceive(ByVal ar As IAsyncResult) '完成接收資料 recvLength = AcceptClient.EndReceive(ar) '繼續開始接收資料 SocketClient.BeginReceive( data, 0, data.Length, SocketFlags.None , _ End Sub
Socket類別非同步傳送資料 '建立委派 SendData = New AsyncCallback(AddressOf OnSend) '開始傳送資料 SocketClient.BeginSend(byteSend, 0, byteSend.Length, _ SocketFlags.None, SendData, SocketClient) Public Sub OnSend(ByVal ar As IAsyncResult) '結束傳送資料 SocketClient.EndSend(ar) End Sub
客戶端Socket非同步連接至伺服端Socket '建立委派 Connect = New AsyncCallback(AddressOf OnConnect) '開始連接至Socket伺服端 SocketClient.BeginConnect(IPEndPoint, Connect, SocketClient) Public Sub OnConnect(ByVal ar As IAsyncResult) '結束連接至Socket伺服端 SocketClient.EndConnect(ar) End Sub