.NET BCL Series (TCP Client / HTTP Client) | Network
2022-07-01
筆記 .NET Base Class Library 各式基礎函式庫的使用原理與技巧,讓開發 .NET 程式自然且流暢 🙂
說明
TCPClient
測試伺服器與特定 Port 否啟用,並且以 1 秒鐘立刻逾時 (timeout)。
var client = new System.Net.Sockets.TcpClient();
var success = false;
try
{
var task = client.BeginConnect("web1", 80, null, null);
success = task.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1));
}
catch (Exception)
{
}
HttpClient
.NET 推薦在 HTTP 互動的類別上優先使用 HttpClient,早期的 WebClient 以及 WebRequest 已經被警示為 Deprecated。但 HttpClient 無法與 FTP 互動以及顯示傳送進度,仍不可完全取代 WebClient。
.NET Framework 當中, HttpClient 的底層仍是 HttpWebRequest 到了 .NET 才有獨立的 HttpClient 以 SocketsHttpHandler 實作
using System.Net.Http;
using System.Net;
static readonly HttpClient client = new HttpClient();
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
HttpResponseMessage response = await client.GetAsync("https://httpstat.us/404");
Console.WriteLine((int)response.StatusCode);
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
預設 HttpClient 可以回應各種 StatusCode,如果要限制成功 (Success 200) 的情況,可以使用 response.EnsureSuccessStatusCode 讓不是 200 的 StatusCode Raise Exception。
response.EnsureSuccessStatusCode();
預設上 .NET 會自動選擇適合的 TLS Portocol,但可能碰到回應 Server 只支援 TLS 1.2 以上而無法成功建立連線的問題,這個時候可以透過 ServicePointManager.SecurityProtocol 來指定 Client 端要使用的 TLS 版本。
System.Net.SecurityProtocolType.Ssl3
System.Net.SecurityProtocolType.Tls
System.Net.SecurityProtocolType.Tls11
System.Net.SecurityProtocolType.Tls12
System.Net.SecurityProtocolType.Tls13
NTLM
在 HttpClientHandler 設定 UseDefaultCredentials 為 true,HttpClient 物件在發送 HTTP 請求時,就會使用目前執行緒的 Windows 身分來進行驗證 (NTLM)。
using (var client =
new HttpClient(new HttpClientHandler { UseDefaultCredentials = true }))
{
using (var response = await client.GetAsync(url))
{
if (response.IsSuccessStatusCode)
{
result = await response.Content.ReadAsStringAsync();
}
}
}
HTTP Upload File
HttpClient
下列是伺服器端負責接收檔案上傳的 Code,可以接收多個檔案。
Controller.cs
public ActionResult Upload(HttpPostedFileBase[] files)
{
var fileUploads = new List<FiledUploaded> { };
foreach (var file in files)
{
var fileUpload = new FiledUploaded(file, Server.MapPath("~/Uploads/"));
file.SaveAs(Path.Combine(fileUpload.ServerPath, fileUpload.GuidName));
fileUploads.Add(fileUpload);
}
return View(fileUploads);
}
下列是 Client 端負責將檔案進行上傳的 Code,示範多檔上傳的方式。
UploadProgram.cs
using System.Net;
using System.Net.Http;
string url = "https://localhost:12345/Home/Upload";
var formData = new MultipartFormDataContent();
formData.Add(
new StreamContent(new FileStream(@"C:\temp\sun.png", FileMode.Open))
,"files" // name Mapping Controler's HttpPostedFileBase[] Parameters
,"moon.png" // fileName
);
formData.Add(
new StreamContent(new FileStream(@"C:\temp\moon.png", FileMode.Open))
,"files"
,"sun.png"
);
using (var client = new HttpClient(new HttpClientHandler { UseDefaultCredentials = true })){
var httpResponseMessage = await client.SendAsync(
new HttpRequestMessage(HttpMethod.Post, url)
{
Content = formData
});
Console.WriteLine(httpResponseMessage.StatusCode);
}
需要注意的是 MultipartFormDataContent
所加入的 HttpContent 所指定的 name 必須要與接收伺服器端的 Controller 的參數一致,本例都是 files。
如果接收端需要 Windows 驗證,可以在 HttpClient 使用 HttpClientHandler
並且使用 UseDefaultCredentials
會使用目前 Client 端登入的 Windows 驗證進行傳送。