[220321] HttpWebRequest(WebRequest), WebClient, HttpClient
.NET Framework에서 작업할 때 HTTP 요청을 사용하기 위해서는 세가지 방법이 있습니다.
WebRequest (HttpWebRequest)
WebClient
HttpClient
System.Net.WebRequest
System.Net.WebRequest 는 추상 클래스 입니다. 따라서 이 클래스를 사용하여 HTTP 요청을 사용하려면 HttpWebRequest 또는 FileWebRequest 를 사용해서 작성해야 한다고 합니다.
이 클래스를 이용해서 작업시, Header, Cookie, Protocol 및 시간초과에 액세스 하고 작업할 수 있는 장점이 있으며,
HTTP 요청에 대한 세밀한 컨트롤이 가능한 장점이 있습니다.
가장 많이 접한 class 또한 HttpWebRequest class 였습니다.
System.Net.Http.HttpClient
HttpClient 는 .NET Framework 4.5에서 도입되었습니다.
HttpClient는 HttpWebRequest의 유연성과 WebClient의 단순성을 결합하여 제공하기 때문에, 해당 프레임워크를 사용하는 환경이라면, HttpClient 를 사용하는 것을 권장하고 있습니다.
HttpWebRequest는 요청/응답 객체에 대한 많은 제어 기능을 제공하기 때문에, 이러한 기능이 필요하다면 HttpClient 보다는 HttpWebRequest를 사용해야 합니다만, HttpClient는 FTP를 지원하지 않습니다.
HttpClient의 모든 I/O 바인딩 메소드는 비동기식이며, 동일한 HttpClient 인스턴스를 사용해서 동시 요청을 수행할 수 있습니다. 즉, 동기 비동기식을 모두 제공합니다.
HttpClient는 한 번 인스턴스화되고 응용프로그램의 수명주기 전체에서 재사용 하도록 설계되었습니다.
만약 반복적으로 HttpClient를 사용한다면, 매번 할당 후 제거하는 방식이 아닌 한번 사용한 객체를 재사용하도록 설계하여야 합니다. new 키워드로 HttpClient를 생성 할 때마다 사용 가능한 소켓이 많은 트래픽으로 소진되기 때문에 SocketException이 발생 할 수 있습니다.
그러므로 HttpClient의 권장 사용 방법은 단일 공유 HttpClient 인스턴스를 작성 하는 것 입니다.
1. .NET Framework 4.5 를 이용하는 환경이라면 HttpClient 를 사용하는 것을 권장합니다.
2. 단. HttpClient를 사용한다면, 단일화된 HttpClient 인스턴스를 생성하고 재사용 하는 것이 좋습니다. (static)
3. HttpClient는 WebClient를 완전히 대체하지 못하기 때문에, 필요에 따라 WebClient를 사용해야 합니다.
4. .NET Framework 4.5 버전을 사용 못하는 환경이라면, HttpWebRequest 와 WebClient의 장점을 비교해서 사용하시면 됩니다.
5. 요청 및 응답에 따른 다양한 제어 및 헤더, 쿠키등등 HTTP의 구성요소를 사용해야 한다면 HttpWebRequest 를 이용하는 것이 좋습니다.
https://holjjack.tistory.com/150
직접 사용한 예시
using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Net;
using System.Text;
namespace EmployeesCRUD
{
internal class EmpHttpRequest
{
public static string GetEmployeesList()
{
string result = string.Empty;
try
{
WebClient client = new WebClient();
//특정 요청 헤더값을 추가
//client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
using (Stream data = client.OpenRead("http://localhost:8081/getEmployeesList"))
{
using (StreamReader reader = new StreamReader(data))
{
result = reader.ReadToEnd();
reader.Close();
data.Close();
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString()); //통신 실패
}
return result;
}
public static string AddEmployeePost(JObject jsonStr)
{
// url를 통해 HttpWebRequest 클래스를 생성한다.
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://localhost:8081/addEmployee");
// 해더의 메소드를 정의한다.
httpWebRequest.Method = "POST";
// 해더의 ContentType를 정의한다.
httpWebRequest.ContentType = "application/json; charset=utf-8";
// 프로퍼티로 정의된 해더의 경우, 아래와 같이 정의할 경우 에러가 발생한다. (???)
//request.Headers["Upgrade-Insecure-Requests"] = "1";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(jsonStr);
}
//
HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
string result = streamReader.ReadToEnd();
Console.WriteLine(result);
return result;
}
}
public static string RemoveEmployees(string empNo)
{
//get 문자열
WebClient client = new WebClient();
client.Encoding = Encoding.UTF8;
StringBuilder sb = new StringBuilder();
sb.Append("http://localhost:8081/removeEmployees?");
sb.AppendFormat("empNo={0}", empNo);
//웹 서버에서 HTML이나 문자열을 다운로드 받기 위해서 DownloadString(), get형식
string result = client.DownloadString(sb.ToString());
Console.WriteLine(result);
return result;
}
public static string EditEmployeePost(JObject jsonStr)
{
string result = String.Empty;
WebClient client = new WebClient();
client.Encoding = Encoding.UTF8;
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
try
{
//지정된 문자열을 지정된 리소스에 업로드 UploadString(), post형식
result = client.UploadString("http://localhost:8081/editEmployee", jsonStr.ToString());
}
catch (Exception e)
{
Console.WriteLine(e.ToString()); //통신 실패
}
return result;
}
}
}