使用通訊端來透過 TCP 傳送和接收資料
在您使用通訊端與遠端裝置進行通訊之前,必須先使用通訊協定和網路位址資訊初始化通訊端。 Socket 類別的建構函式所擁有的參數,可指定通訊端用來建立連線的位址家族、通訊端類型和通訊協定類型。 將用戶端通訊端連線到伺服器通訊端時,用戶端會使用 IPEndPoint
物件來指定伺服器的網路位址。
建立 IP 端點
使用 System.Net.Sockets 時,您會將網路端點表示為 IPEndPoint 物件。 IPEndPoint
是以 IPAddress 及其對應的連接埠號碼來建構。 在透過 Socket 起始交談之前,您要先建立應用程式和遠端目的地之間的資料管道。
TCP/IP 會使用網路位址和服務連接埠編號來唯一識別服務。 網路位址可識別特定網路目的地;連接埠號碼則可識別該裝置上要連線的特定服務。 網路位址和服務連接埠的組合稱為端點,在 .NET 中是以 EndPoint 類別表示。 每個支援的位址系列已定義 EndPoint
的子系;對於 IP 位址系列,此類別是 IPEndPoint。
Dns 類別會提供網域名稱服務給使用 TCP/IP 網際網路服務的應用程式。 GetHostEntryAsync 方法會查詢 DNS 伺服器,以將使用者易記的網域名稱 (例如 "host.contoso.com") 對應到數字的網際網路位址 (例如 192.168.1.1
)。 GetHostEntryAsync
會傳回 Task<IPHostEntry>
,在等待時其中包含位址和所要求名稱之別名的清單。 在大部分情況下,您可以使用 AddressList 陣列中傳回的第一個位址。 下列程式碼可取得包含伺服器 host.contoso.com
之 IP 位址的 IPAddress。
IPHostEntry ipHostInfo = await Dns.GetHostEntryAsync("host.contoso.com");
IPAddress ipAddress = ipHostInfo.AddressList[0];
提示
針對手動測試和偵錯目的,您通常可以使用 GetHostEntryAsync 方法以及從 Dns.GetHostName() 值取得的結果主機名稱,將 localhost 名稱解析為 IP 位址。 請考慮下列程式碼片段:
var hostName = Dns.GetHostName();
IPHostEntry localhost = await Dns.GetHostEntryAsync(hostName);
// This is the IP address of the local machine
IPAddress localIpAddress = localhost.AddressList[0];
Internet Assigned Numbers Authority (IANA) 定義了通用服務的連接埠號碼。 如需詳細資訊,請參閱 IANA:服務名稱和傳輸通訊協定連接埠號碼登錄)。 其他服務的已登錄連接埠編號範圍可以是 1,024 到 65,535。 下列程式碼會合併 host.contoso.com
的 IP 位址與連接埠號碼,以建立連線的遠端端點。
IPEndPoint ipEndPoint = new(ipAddress, 11_000);
在判斷遠端裝置的位址並選擇要用於連線的連接埠之後,應用程式可以建立與遠端裝置的連線。
建立 Socket
用戶端
建立 endPoint
物件之後,建立用戶端通訊端以連線到伺服器。 連線通訊端之後,就可以從伺服器通訊端連線傳送和接收資料。
using Socket client = new(
ipEndPoint.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp);
await client.ConnectAsync(ipEndPoint);
while (true)
{
// Send message.
var message = "Hi friends 👋!<|EOM|>";
var messageBytes = Encoding.UTF8.GetBytes(message);
_ = await client.SendAsync(messageBytes, SocketFlags.None);
Console.WriteLine($"Socket client sent message: \"{message}\"");
// Receive ack.
var buffer = new byte[1_024];
var received = await client.ReceiveAsync(buffer, SocketFlags.None);
var response = Encoding.UTF8.GetString(buffer, 0, received);
if (response == "<|ACK|>")
{
Console.WriteLine(
$"Socket client received acknowledgment: \"{response}\"");
break;
}
// Sample output:
// Socket client sent message: "Hi friends 👋!<|EOM|>"
// Socket client received acknowledgment: "<|ACK|>"
}
client.Shutdown(SocketShutdown.Both);
在上述 C# 程式碼中:
具現化具有指定
endPoint
執行個體位址系列、SocketType.Stream、和 ProtocolType.Tcp 的新Socket
物件。使用
endPoint
執行個體作為引數呼叫 Socket.ConnectAsync 方法。在
while
迴圈中:- 使用 Socket.SendAsync 將訊息編碼並傳送至伺服器。
- 將傳送的訊息寫入主控台。
- 使用 Socket.ReceiveAsync 初始化緩衝區以接收來自伺服器的資料。
- 當
response
是通知時,會寫入主控台並結束迴圈。
最後,
client
會呼叫 Socket.Shutdown 指定 SocketShutdown.Both,這會關閉傳送和接收作業。
建立 Socket
伺服器
若要建立伺服器通訊端,endPoint
物件可以在任何 IP 位址上接聽連入連線,但必須指定連接埠號碼。 建立通訊端之後,伺服器就可以接受連入連線,並與用戶端通訊。
using Socket listener = new(
ipEndPoint.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp);
listener.Bind(ipEndPoint);
listener.Listen(100);
var handler = await listener.AcceptAsync();
while (true)
{
// Receive message.
var buffer = new byte[1_024];
var received = await handler.ReceiveAsync(buffer, SocketFlags.None);
var response = Encoding.UTF8.GetString(buffer, 0, received);
var eom = "<|EOM|>";
if (response.IndexOf(eom) > -1 /* is end of message */)
{
Console.WriteLine(
$"Socket server received message: \"{response.Replace(eom, "")}\"");
var ackMessage = "<|ACK|>";
var echoBytes = Encoding.UTF8.GetBytes(ackMessage);
await handler.SendAsync(echoBytes, 0);
Console.WriteLine(
$"Socket server sent acknowledgment: \"{ackMessage}\"");
break;
}
// Sample output:
// Socket server received message: "Hi friends 👋!"
// Socket server sent acknowledgment: "<|ACK|>"
}
在上述 C# 程式碼中:
具現化具有指定
endPoint
執行個體位址系列、SocketType.Stream、和 ProtocolType.Tcp 的新Socket
物件。listener
會使用endPoint
執行個體作為引數來呼叫 Socket.Bind 方法,以將通訊端與網路位址產生關聯。系統會呼叫 Socket.Listen() 方法來接聽連入連線。
listener
會呼叫 Socket.AcceptAsync 方法來接受handler
通訊端上的連入連線。在
while
迴圈中:- 呼叫 Socket.ReceiveAsync 以接收用戶端的資料。
- 收到資料時,會解碼並寫入主控台。
- 如果
response
訊息結尾為<|EOM|>
,則會使用 Socket.SendAsync 將通知傳送至用戶端。
執行範例用戶端和伺服器
先啟動伺服器應用程式,然後啟動用戶端應用程式。
dotnet run --project socket-server
Socket server starting...
Found: 172.23.64.1 available on port 9000.
Socket server received message: "Hi friends 👋!"
Socket server sent acknowledgment: "<|ACK|>"
Press ENTER to continue...
用戶端應用程式會將訊息傳送至伺服器,而伺服器會以通知回應。
dotnet run --project socket-client
Socket client starting...
Found: 172.23.64.1 available on port 9000.
Socket client sent message: "Hi friends 👋!<|EOM|>"
Socket client received acknowledgment: "<|ACK|>"
Press ENTER to continue...