Windows 10 的 UDP 與 TCP 網路通訊實作案例二(軟體開發、軟件開發、程式設計、程式開發)
這篇文章主要是續之前另外一篇文章 UDP 網路通訊處理,這次是繼續講解 TCP 網路通訊處理,與UDP 協定不同的是,TCP協定是更加嚴謹,它是基於確認連接是可靠性的,也就是在發生通訊傳輸前,客戶端(Client)必須確認是連接到伺服器(Server)端,因為 TCP 對數據封包的次序與完整性要求相對嚴格,這樣才能確保數據傳輸過程可以正確無誤地送達目的地,所以 TCP 就常用在 文件的傳送,如Line聊天的檔案傳送、Skype 檔案的傳送等。
在 Widnows 10 Universal APP 平台下(UWP ),是透過一個 StreamSocket 類別來提供 TCP 網路通訊傳輸協定的 Socket 功能.
在 Client 端(客戶端)大致我們遵守以下幾個步驟:
1.建立一個 StreamSocket 實體物件。
2.呼叫 StreamSocket.ConnectAsync 方法,來與 Server 端作連接要求。
3.使用 OutputStream 屬性所返回的輸出流(Stream),就可以進行發送資料;
而 InputStream 屬性則是返回輸入流,是用在接受資料。
4.切記當不再使用 Socket 時,呼叫 Dispose 方法來釋放其所佔用的相關資源。
在 Server 端 (伺服器),我們則需要使用一個 StreamSocketListener 物件,綁定繫結 本機的位址跟Port,來監聽 客戶端(Client)的連接請求服務,而當監聽到客戶發出的請求服務時,會引發另外一個事件 ConnectionReceived 事件,從這個事件的Arg參數,我們可以獲取一個與客戶端進行通訊的 StreamSocket 物件。
上面簡單描述原理,以及程式撰寫大致步驟原理,我一樣習慣來個實際寫作案例來引導,我一樣為了簡單化,我把 Server 端界面與 Client 端界面放在一起,這樣這個範例程式可以充當伺客戶器角色也可以當客戶端角色,在實作案例中 客戶端可以選擇一個圖片已經輸入一些文字內容來描述圖片,最後可以發送圖片跟文字內容給伺服器端,當然伺服器端會馬上監聽到有傳輸服務請求,立即結束資料,並顯示在伺服器端的界面。
系統畫面如下圖
(Server 端)

(Client 端)

下面是相關的界面 XAML Code:
<Pivot>
<PivotItem Header="伺服器(Server 端模擬)">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel>
<TextBlock Text="Server IP Address:" Height="30" Margin="0,0,-0.333,0"/>
<TextBlock x:Name="tbSvIP" FontSize="24" IsTextSelectionEnabled="True" Height="30" Margin="0,0,-0.333,0"/>
</StackPanel>
<ListBox Name="lbItems" Grid.Row="1" Margin="6,15,6,5">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Width="50" Height="50" Stretch="UniformToFill" Source="{Binding Path=Image}"/>
<TextBlock Grid.Column="1" TextWrapping="Wrap" FontSize="18" Text="{Binding Path=Text}" Margin="15,0,0,0"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</PivotItem>
<PivotItem Header="客戶端(Client 端模擬)">
<StackPanel>
<TextBox Name="txtServerIp" Header="伺服器IP:"/>
<Image Name="img" Width="150" Height="150" HorizontalAlignment="Left"/>
<Button Content="挑選圖片..." Click="OnPickImagFile"/>
<TextBox Name="txtContent" Header="圖片描述:" Height="120"/>
<Button Content="傳送資料" HorizontalAlignment="Stretch" Click="OnSend"/>
</StackPanel>
</PivotItem>
</Pivot>
現在來看主要核心程式碼
一開始我宣告 一個 LISTEN_PORT=“1688”,作為 Server 端監聽的端口。
然後也宣告一個 StreamSocketListener 類別的 listener 欄位。
相關程式我也詳細註解了,主要是在 Loaded事件時,建立對應的監聽事件 ConnectionReceived 、以及使用 BindServiceNameAsync 方法指定監聽的Port。

接下來重點在 ConnectionReceived 事件,專門用於接受到 Client 端發出的請求數據。
private async void listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
string text = string.Empty;
IRandomAccessStream imgStream = new InMemoryRandomAccessStream();
// 處理從 Client 端接受到的訊息
using (StreamSocket socket = args.Socket)
{
using (DataReader reader = new DataReader(socket.InputStream))
{
try
{
// 讀出第一個數字,表示文件的長度
await reader.LoadAsync(sizeof(uint));
uint len = reader.ReadUInt32();
await reader.LoadAsync(len);
IBuffer buffer = reader.ReadBuffer(len);
// 寫入 Stream
await imgStream.WriteAsync(buffer);
await reader.LoadAsync(sizeof(uint));
// 再次讀入字串長度
len = reader.ReadUInt32();
// 讀出字串的內容
if (len > 0)
{
await reader.LoadAsync(len);
text = reader.ReadString(len);
}
}
catch (Exception ex)
{
DisplayErrMessage(ex.Message);
}
}
}
// 顯示接受到的客戶端訊息內容
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
BitmapImage bmp = new BitmapImage();
bmp.DecodePixelWidth = 50;
imgStream.Seek(0);
bmp.SetSource(imgStream);
imgStream.Dispose();
lbItems.Items.Add(new { Image = bmp, Text = text });
});
}
再來 Client 端,主要是選好圖片內容、以及輸入文字描述後,執行【傳送資料】按鈕,而對應的程式碼,如下,我也寫上對應的註解
private async void OnSend(object sender, RoutedEventArgs e)
{
if (txtServerIp.Text.Length == 0)
{
DisplayErrMessage("請輸入伺服器服的IP位置");
return;
}
IBuffer bufferImg = img.Tag as IBuffer;
if (bufferImg == null)
{
DisplayErrMessage("請選擇圖像");
return;
}
Button b = sender as Button;
b.IsEnabled = false;
using (StreamSocket socket = new StreamSocket())
{
try
{
// 發出連線請求
await socket.ConnectAsync(new HostName(txtServerIp.Text), LISTEN_PORT);
// 準備傳送資料(圖片跟文字)
using (DataWriter writer = new DataWriter(socket.OutputStream))
{
// 首先寫入圖片
uint len = bufferImg.Length;
writer.WriteUInt32(len); //長度
writer.WriteBuffer(bufferImg);
// 寫入文字內容
if (txtContent.Text.Length == 0)
{
writer.WriteUInt32(0);
}
else
{
len = writer.MeasureString(txtContent.Text);
writer.WriteUInt32(len); //長度
writer.WriteString(txtContent.Text);
}
// 正式提交
await writer.StoreAsync();
}
txtContent.Text = "";
}
catch (Exception ex)
{
DisplayMessage(ex.Message);
}
}
b.IsEnabled = true;
}
整個程式執行結果畫面
(客戶端)

(伺服器端)

網智數位-軟體開發(軟件開發)
針對各特殊產業都可以量身定做符合貴公司的需求,別人無法克服的就是我們的挑戰
業務合作、軟體委外開發
業務窗口:allen@netqna.com
聯繫電話:0920-883-870
skype: netqna
line:netqna
微信:netqna
黃先生 Allen
沒有留言:
張貼留言
如您對本文有任何建議或意見,歡迎您留下您寶貴的意見!