Windows 8 市集應用程式(Windows Store Apps)提供豐富的網路通訊 API,其中 Windows.Networking.Sockets 命名空間支援 TCP 與 UDP 兩種傳輸協定,讓開發者能建立即時通訊、自訂協定伺服器或輕量級資料傳輸應用。本文透過三個完整範例,示範如何在同一個應用程式中同時扮演伺服器與用戶端角色,實作 TCP 通訊、自訂 HTTP 伺服器與 UDP 資料傳遞。
StreamSocketListener:TCP 伺服器端監聽器StreamSocket:TCP 用戶端連線DataWriter / DataReader:資料序列化與反序列化Package.appxmanifest 加入 <Capability Name="privateNetworkClientServer" />簡單的 StackPanel 佈局,包含四個按鈕(啟動監聽、連線伺服器、發送資料、關閉連線)與一個 TextBlock 顯示訊息記錄。
private async void btnStartListener_Click(object sender, RoutedEventArgs e) {
_listener = new StreamSocketListener();
_listener.ConnectionReceived += _listener_ConnectionReceived;
try {
await _listener.BindServiceNameAsync("2211");
lblMsg.Text += "已在本機 2211 埠啟動 TCP 監聽" + Environment.NewLine;
} catch (Exception ex) {
// 錯誤處理:取得 SocketErrorStatus 並顯示
}
}
採用自訂協定:前 4 位元組為無號整數標示資料長度,後續為字串內容。使用 DataReader.LoadAsync 非同步讀取標頭與本體,並在 UI 執行緒更新介面。
async void _listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args) {
DataReader reader = new DataReader(args.Socket.InputStream);
// 更新 UI 顯示遠端端點資訊
try {
while (true) {
uint sizeFieldCount = await reader.LoadAsync(sizeof(uint));
if (sizeFieldCount != sizeof(uint)) return;
uint stringLength = reader.ReadUInt32();
uint actualStringLength = await reader.LoadAsync(stringLength);
if (stringLength != actualStringLength) return;
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
lblMsg.Text += "接收到資料: " + reader.ReadString(actualStringLength) + Environment.NewLine;
});
}
} catch (Exception ex) { /* 錯誤處理 */ }
}
private async void btnConnectListener_Click(object sender, RoutedEventArgs e) {
_client = new StreamSocket();
await _client.ConnectAsync(new HostName("127.0.0.1"), "2211");
lblMsg.Text += "已連線至 127.0.0.1:2211" + Environment.NewLine;
}
private async void btnSendData_Click(object sender, RoutedEventArgs e) {
if (_writer == null) _writer = new DataWriter(_client.OutputStream);
string data = "hello webabcd " + DateTime.Now.ToString("HH:mm:ss");
_writer.WriteUInt32(_writer.MeasureString(data)); // 寫入長度標頭
_writer.WriteString(data); // 寫入本體
await _writer.StoreAsync();
lblMsg.Text += "資料已發送: " + data + Environment.NewLine;
}
呼叫 DetachStream() 解除 DataWriter 與 Stream 關聯,再依序 Dispose 用戶端、伺服器物件。
同樣使用 StreamSocketListener 監聽埠 2212,但在 ConnectionReceived 事件中手動解析 HTTP 請求標頭(讀取至 \r\n\r\n),並組裝符合 HTTP/1.1 規範的回應(狀態碼、標頭、內容長度、本體)。
async void _listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args) {
DataReader reader = new DataReader(args.Socket.InputStream);
StringBuilder sb = new StringBuilder();
while (true) {
uint loaded = await reader.LoadAsync(1);
if (loaded != 1) return;
char c = (char)reader.ReadByte();
sb.Append(c);
if (sb.ToString().IndexOf("\r\n\r\n") > 0) {
// 解析完成,組裝回應
string response = "HTTP/1.1 200 OK\r\nContent-Type:text/html\r\nServer:Custom Http Server\r\nContent-Length:2\r\nConnection: Keep-Alive\r\n\r\nok";
DataWriter writer = new DataWriter(args.Socket.OutputStream);
writer.WriteString(response);
await writer.StoreAsync();
sb.Clear();
}
}
}
用戶端使用 HttpClient.GetStringAsync 呼叫 https://localhost:2212/abc.html 驗證伺服器運作。
DatagramSocket 取代 StreamSocketConnectAsync 僅設定預設發送目標MessageReceived,透過 DatagramSocketMessageReceivedEventArgs.GetDataReader() 取得資料private async void btnSendData_Click(object sender, RoutedEventArgs e) {
if (_client == null) {
_client = new DatagramSocket();
await _client.ConnectAsync(new HostName("127.0.0.1"), "2213");
}
if (_writer == null) _writer = new DataWriter(_client.OutputStream);
string data = "hello webabcd " + DateTime.Now.ToString("HH:mm:ss");
_writer.WriteString(data);
await _writer.StoreAsync();
lblMsg.Text += "資料已發送: " + data + Environment.NewLine;
}
private void _listener_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args) {
DataReader dataReader = args.GetDataReader();
uint stringLength = dataReader.UnconsumedBufferLength;
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
lblMsg.Text += "接收到資料: " + dataReader.ReadString(stringLength)
+ " - 來源: " + args.RemoteAddress.RawName + ":" + args.RemotePort + Environment.NewLine;
});
}
三個範例完整展示 Windows 8 市集應用程式中 Socket 程式設計的核心模式:TCP 可靠串流、自訂應用層協定(HTTP)、UDP 無連線資料報。開發者可根據即時性、可靠性與負載需求選擇適當方案。