C# 网络编程--基础核心内容

在现今软件开发中,网络编程是非常重要的一部分,本文简要介绍下网络编程的概念和实践。
C#网络编程的主要内容包括以下几个方面‌:
: Alt
上图引用大佬的图,大家也关注一下,有技术有品质,有国有家,情怀满满的杨老师(不得不去仰慕一番哈哈)
https://blog.csdn.net/Eastmount/article/details/9321153

1. 底层网络协议类‌

如NetworkStream、TcpClient与TcpListener、UdpClient等,这些类提供了更底层的网络操作接口,适用于需要直接控制网络连接和数据处理的情况‌

1. TCP 通信

使用 TcpListener 和 TcpClient 进行 通讯

  • TCP 服务器端示例
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

class TcpServerExample
{
    static async Task Main(string[] args)
    {
        // 创建一个 TCP/IP 套接字
        TcpListener listener = new TcpListener(IPAddress.Any, 13000);
        listener.Start();
        Console.WriteLine("Server started. Waiting for connections...");

        while (true)
        {
            // 接受传入连接
            TcpClient client = await listener.AcceptTcpClientAsync();
            Console.WriteLine("Client connected.");

            // 处理客户端请求
            _ = HandleClient(client);
        }
    }

    static async Task HandleClient(TcpClient client)
    {
        try
        {
            NetworkStream stream = client.GetStream();

            // 接收数据
            byte[] buffer = new byte[256];
            int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
            string request = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            Console.WriteLine("Received: " + request);

            // 发送响应
            string response = "Hello, Client!";
            byte[] responseData = Encoding.ASCII.GetBytes(response);
            await stream.WriteAsync(responseData, 0, responseData.Length);
            Console.WriteLine("Sent: " + response);

            // 关闭连接
            client.Close();
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message);
        }
    }
}
  • TCP 客户端示例
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

class TcpClientExample
{
    static async Task Main(string[] args)
    {
        try
        {
            // 创建一个 TCP/IP 套接字
            TcpClient client = new TcpClient();
            await client.ConnectAsync("127.0.0.1", 13000);
            Console.WriteLine("Connected to server.");

            NetworkStream stream = client.GetStream();

            // 发送数据
            string message = "Hello, Server!";
            byte[] data = Encoding.ASCII.GetBytes(message);
            await stream.WriteAsync(data, 0, data.Length);
            Console.WriteLine("Sent: " + message);

            // 接收响应
            byte[] buffer = new byte[256];
            int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
            string response = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            Console.WriteLine("Received: " + response);

            // 关闭连接
            client.Close();
        }
        catch (Exception e)
        {
            Console.WriteLine("Error: " + e.Message);
        }
    }
}

2. UDP 通信

使用 UdpClient 进行通讯

  • UDP 服务器端示例
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

class UdpServerExample
{
    static async Task Main(string[] args)
    {
        // 创建一个 UDP/IP 套接字
        UdpClient listener = new UdpClient(11000);
        IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
        Console.WriteLine("UDP Server started. Listening on port 11000...");

        while (true)
        {
            // 接收数据
            byte[] buffer = await listener.ReceiveAsync();
            string request = Encoding.ASCII.GetString(buffer);
            Console.WriteLine("Received: " + request + " from " + remoteEndPoint.ToString());

            // 发送响应
            string response = "Hello, Client!";
            byte[] responseData = Encoding.ASCII.GetBytes(response);
            await listener.SendAsync(responseData, responseData.Length, remoteEndPoint);
            Console.WriteLine("Sent: " + response);
        }
    }
}
  • UDP 客户端示例
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

class UdpClientExample
{
    static async Task Main(string[] args)
    {
        try
        {
            // 创建一个 UDP/IP 套接字
            UdpClient client = new UdpClient();
            IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000);

            // 发送数据
            string message = "Hello, Server!";
            byte[] data = Encoding.ASCII.GetBytes(message);
            await client.SendAsync(data, data.Length, remoteEP);
            Console.WriteLine("Sent: " + message);

            // 接收响应
            UdpReceiveResult result = await client.ReceiveAsync();
            string response = Encoding.ASCII.GetString(result.Buffer);
            Console.WriteLine("Received: " + response + " from " + result.RemoteEndPoint.ToString());

            // 关闭连接
            client.Close();
        }
        catch (Exception e)
        {
            Console.WriteLine("Error: " + e.Message);
        }
    }
}

3. 使用 NetworkStream 进行自定义协议通信

NetworkStream 提供了一个流式接口,可以用于读取和写入网络数据。以下是一个使用 NetworkStream 的示例,展示如何实现一个简单的自定义协议。

  • 自定义协议服务器端示例
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

class CustomProtocolServerExample
{
    static async Task Main(string[] args)
    {
        // 创建一个 TCP/IP 套接字
        TcpListener listener = new TcpListener(IPAddress.Any, 13000);
        listener.Start();
        Console.WriteLine("Server started. Waiting for connections...");

        while (true)
        {
            // 接受传入连接
            TcpClient client = await listener.AcceptTcpClientAsync();
            Console.WriteLine("Client connected.");

            // 处理客户端请求
            _ = HandleClient(client);
        }
    }

    static async Task HandleClient(TcpClient client)
    {
        try
        {
            NetworkStream stream = client.GetStream();

            // 接收数据
            byte[] buffer = new byte[256];
            int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
            string request = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            Console.WriteLine("Received: " + request);

            // 解析自定义协议
            string[] parts = request.Split(':');
            if (parts.Length == 2 && parts[0] == "COMMAND")
            {
                string command = parts[1];
                Console.WriteLine("Command: " + command);

                // 处理命令并生成响应
                string response = "ACK: Command received";
                byte[] responseData = Encoding.ASCII.GetBytes(response);
                await stream.WriteAsync(responseData, 0, responseData.Length);
                Console.WriteLine("Sent: " + response);
            }
            else
            {
                string response = "ERROR: Invalid command format";
                byte[] responseData = Encoding.ASCII.GetBytes(response);
                await stream.WriteAsync(responseData, 0, responseData.Length);
                Console.WriteLine("Sent: " + response);
            }

            // 关闭连接
            client.Close();
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message);
        }
    }
}
  • 自定义协议客户端示例
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

class CustomProtocolClientExample
{
    static async Task Main(string[] args)
    {
        try
        {
            // 创建一个 TCP/IP 套接字
            TcpClient client = new TcpClient();
            await client.ConnectAsync("127.0.0.1", 13000);
            Console.WriteLine("Connected to server.");

            NetworkStream stream = client.GetStream();

            // 发送自定义协议命令
            string message = "COMMAND:Hello";
            byte[] data = Encoding.ASCII.GetBytes(message);
            await stream.WriteAsync(data, 0, data.Length);
            Console.WriteLine("Sent: " + message);

            // 接收响应
            byte[] buffer = new byte[256];
            int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
            string response = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            Console.WriteLine("Received: " + response);

            // 关闭连接
            client.Close();
        }
        catch (Exception e)
        {
            Console.WriteLine("Error: " + e.Message);
        }
    }
}

2.Socket编程‌

也就是我们常说的“套接字”,Socket类在System.Net.Sockets命名空间下,是最基本的网络操作类,封装了网络连接的创建和关闭、数据的收发以及网络状态监控等功能。通过Socket类,可以实现基于TCPUDP的网络通信‌。

1. 使用 Socket 类进行 TCP 通信

TCP 服务器端示例
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

class TcpServerExample
{
    static async Task Main(string[] args)
    {
        // 创建一个 TCP/IP 套接字
        Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        // 绑定套接字到本地端口
        IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 13000);
        listener.Bind(localEndPoint);

        // 监听传入连接
        listener.Listen(10);
        Console.WriteLine("Server started. Waiting for connections...");

        while (true)
        {
            // 接受传入连接
            Socket handler = await listener.AcceptAsync();
            Console.WriteLine("Client connected.");

            // 处理客户端请求
            _ = HandleClient(handler);
        }
    }

    static async Task HandleClient(Socket handler)
    {
        try
        {
            // 接收数据
            byte[] buffer = new byte[256];
            int bytesReceived = await handler.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
            string request = Encoding.ASCII.GetString(buffer, 0, bytesReceived);
            Console.WriteLine("Received: " + request);

            // 发送响应
            string response = "Hello, Client!";
            byte[] responseData = Encoding.ASCII.GetBytes(response);
            await handler.SendAsync(new ArraySegment<byte>(responseData), SocketFlags.None);
            Console.WriteLine("Sent: " + response);

            // 关闭连接
            handler.Shutdown(SocketShutdown.Both);
            handler.Close();
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message);
        }
    }
}
TCP 客户端示例
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

class TcpClientExample
{
    static async Task Main(string[] args)
    {
        try
        {
            // 创建一个 TCP/IP 套接字
            Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            // 连接到服务器
            IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 13000);
            await client.ConnectAsync(remoteEP);
            Console.WriteLine("Connected to server.");

            // 发送数据
            string message = "Hello, Server!";
            byte[] data = Encoding.ASCII.GetBytes(message);
            await client.SendAsync(new ArraySegment<byte>(data), SocketFlags.None);
            Console.WriteLine("Sent: " + message);

            // 接收响应
            byte[] buffer = new byte[256];
            int bytesReceived = await client.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
            string response = Encoding.ASCII.GetString(buffer, 0, bytesReceived);
            Console.WriteLine("Received: " + response);

            // 关闭连接
            client.Shutdown(SocketShutdown.Both);
            client.Close();
        }
        catch (Exception e)
        {
            Console.WriteLine("Error: " + e.Message);
        }
    }
}

2. 使用 Socket 类进行 UDP 通信

UDP 服务器端示例
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

class UdpServerExample
{
    static async Task Main(string[] args)
    {
        // 创建一个 UDP/IP 套接字
        Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

        // 绑定套接字到本地端口
        IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 11000);
        listener.Bind(localEndPoint);

        Console.WriteLine("UDP Server started. Waiting for messages...");

        while (true)
        {
            // 接收数据
            EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
            byte[] buffer = new byte[256];
            int bytesReceived = await listener.ReceiveFromAsync(new ArraySegment<byte>(buffer), SocketFlags.None, remoteEndPoint);
            string request = Encoding.ASCII.GetString(buffer, 0, bytesReceived);
            Console.WriteLine("Received: " + request + " from " + remoteEndPoint.ToString());

            // 发送响应
            string response = "Hello, Client!";
            byte[] responseData = Encoding.ASCII.GetBytes(response);
            await listener.SendToAsync(new ArraySegment<byte>(responseData), SocketFlags.None, remoteEndPoint);
            Console.WriteLine("Sent: " + response);
        }
    }
}
UDP 客户端示例
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

class UdpClientExample
{
    static async Task Main(string[] args)
    {
        try
        {
            // 创建一个 UDP/IP 套接字
            Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            // 连接到服务器
            IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000);

            // 发送数据
            string message = "Hello, Server!";
            byte[] data = Encoding.ASCII.GetBytes(message);
            await client.SendToAsync(new ArraySegment<byte>(data), SocketFlags.None, remoteEP);
            Console.WriteLine("Sent: " + message);

            // 接收响应
            EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
            byte[] buffer = new byte[256];
            int bytesReceived = await client.ReceiveFromAsync(new ArraySegment<byte>(buffer), SocketFlags.None, remoteEndPoint);
            string response = Encoding.ASCII.GetString(buffer, 0, bytesReceived);
            Console.WriteLine("Received: " + response + " from " + remoteEndPoint.ToString());

            // 关闭连接
            client.Close();
        }
        catch (Exception e)
        {
            Console.WriteLine("Error: " + e.Message);
        }
    }
}

注意事项

  1. 异常处理:使用 try-catch 块来捕获和处理异常。
  2. 资源管理:确保在使用完 Socket 后调用 Close 方法来释放资源。
  3. 并发处理:对于服务器端,通常需要处理多个客户端连接,可以使用多线程或异步编程来提高并发性能。
  4. 超时设置:对于 TCP 连接,可以设置超时时间来避免长时间等待。

3.WebSocket通信‌

WebSocket是一种在单个TCP连接上进行全双工通讯的协议。可以使用 System.Net.WebSockets 命名空间中的类来创建 WebSocket 服务器和客户端。WebSocket通信常用于需要实时数据交换的应用场景‌,适用于需要实时数据交换的应用场景,如实时聊天、在线游戏、股票行情等。

1.WebSocket 服务器端示例

以下是一个简单的 WebSocket 服务器端示例,使用 HttpListener 来处理 HTTP 请求并升级为 WebSocket 连接。

using System;
using System.IO;
using System.Net;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

class WebSocketServerExample
{
    static async Task Main(string[] args)
    {
        HttpListener listener = new HttpListener();
        listener.Prefixes.Add("http://localhost:8080/");
        listener.Start();
        Console.WriteLine("WebSocket Server started. Listening on ws://localhost:8080/");

        while (true)
        {
            HttpListenerContext context = await listener.GetContextAsync();
            if (context.Request.IsWebSocketRequest)
            {
                HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(null);
                _ = HandleWebSocketConnection(webSocketContext.WebSocket);
            }
            else
            {
                context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                context.Response.Close();
            }
        }
    }

    static async Task HandleWebSocketConnection(WebSocket webSocket)
    {
        byte[] buffer = new byte[1024 * 4];
        WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

        while (!result.CloseStatus.HasValue)
        {
            string userMessage = Encoding.UTF8.GetString(new ArraySegment<byte>(buffer, 0, result.Count));
            Console.WriteLine("Received: " + userMessage);

            //来自客户端:将消息回传给客户端
            byte[] responseBuffer = Encoding.UTF8.GetBytes("Echo: " + userMessage);
            await webSocket.SendAsync(new ArraySegment<byte>(responseBuffer), result.MessageType, result.EndOfMessage, CancellationToken.None);

            result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
        }

        await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
        webSocket.Dispose();
    }
}

2.WebSocket 客户端示例

以下是一个简单的 WebSocket 客户端示例,使用 ClientWebSocket 类来连接 WebSocket 服务器并进行通信。

using System;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

class WebSocketClientExample
{
    static async Task Main(string[] args)
    {
        using (ClientWebSocket webSocket = new ClientWebSocket())
        {
            Uri serverUri = new Uri("ws://localhost:8080/");
            await webSocket.ConnectAsync(serverUri, CancellationToken.None);
            Console.WriteLine("Connected to server.");

            byte[] buffer = new byte[1024 * 4];

            // 在单独的任务中开始接收消息
            _ = ReceiveMessages(webSocket, buffer);

            // 向服务器发送消息
            while (webSocket.State == WebSocketState.Open)
            {
                Console.Write("Enter message to send: ");
                string message = Console.ReadLine();
                byte[] messageBuffer = Encoding.UTF8.GetBytes(message);
                await webSocket.SendAsync(new ArraySegment<byte>(messageBuffer), WebSocketMessageType.Text, true, CancellationToken.None);
            }
        }
    }

    static async Task ReceiveMessages(ClientWebSocket webSocket, byte[] buffer)
    {
        while (webSocket.State == WebSocketState.Open)
        {
            WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

            if (result.MessageType == WebSocketMessageType.Close)
            {
                await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
                break;
            }

            string receivedMessage = Encoding.UTF8.GetString(new ArraySegment<byte>(buffer, 0, result.Count));
            Console.WriteLine("Received: " + receivedMessage);
        }
    }
}

注意事项

  1. 异常处理:使用 try-catch 块来捕获和处理异常,特别是网络相关的异常。
  2. 资源管理:确保在使用完 WebSocket 后调用 CloseAsync 和 Dispose 方法来释放资源。
  3. 并发处理:对于服务器端,通常需要处理多个客户端连接,可以使用多线程或异步编程来提高并发性能。
  4. 安全性:在生产环境中,建议使用 wss://(WebSocket Secure)来加密通信,防止数据泄露。
  5. 心跳机制:为了保持连接活跃,可以定期发送心跳消息,防止中间设备关闭空闲连接。

4. HTTP请求‌:

可以使用HttpClient、WebClient、HttpRequestMessage和HttpMessageHandler等类来发送HTTP请求。这些类提供了发送GET、POST等请求的方法,并支持异步操作和身份验证等功能‌。

1. HttpClient

HttpClient 是一个现代的、高效的 HTTP 客户端,支持异步操作,适用于 .NET Core 和 .NET Framework。
主要方法
• GetAsync:发送 GET 请求。
• PostAsync:发送 POST 请求。
• PutAsync:发送 PUT 请求。
• DeleteAsync:发送 DELETE 请求。
• SendAsync:发送任意类型的 HTTP 请求。
注意
• 单例模式:HttpClient 实例应该尽量复用,而不是每次请求都创建新的实例。频繁创建 HttpClient 实例会导致资源泄漏和性能问题。
• 异常处理:使用 EnsureSuccessStatusCode 方法来确保请求成功,否则会抛出 HttpRequestException
• 超时设置:设置合理的超时时间,避免长时间等待。
• 取消请求:使用 CancellationToken 来取消长时间运行的请求。
示例代码

using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

class HttpClientExample
{
    private static readonly HttpClient client = new HttpClient();

    static async Task Main(string[] args)
    {
        try
        {
            // 设置超时时间
            client.Timeout = TimeSpan.FromSeconds(30);

            // 发送 GET 请求
            HttpResponseMessage response = await client.GetAsync("https://api.example.com/data");
            response.EnsureSuccessStatusCode(); // 确保请求成功
            string responseBody = await response.Content.ReadAsStringAsync();
            Console.WriteLine("GET Response: " + responseBody);

            // 发送 POST 请求
            var content = new StringContent("{\"key\":\"value\"}", System.Text.Encoding.UTF8, "application/json");
            response = await client.PostAsync("https://api.example.com/post", content);
            response.EnsureSuccessStatusCode();
            responseBody = await response.Content.ReadAsStringAsync();
            Console.WriteLine("POST Response: " + responseBody);
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine("HTTP Error: " + ex.Message);
        }
        catch (TaskCanceledException ex)
        {
            Console.WriteLine("Request canceled: " + ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message);
        }
    }
}

2. WebClient

WebClient 是一个较老的类,提供了简单的同步和异步方法来下载和上传数据。虽然它仍然可用,但推荐使用 HttpClient。
主要方法
• DownloadString:下载字符串内容。
• UploadString:上传字符串内容。
• DownloadFile:下载文件。
• UploadFile:上传文件。

注意
• 同步方法:WebClient 的同步方法会阻塞当前线程,建议使用异步方法。
• 异常处理:使用 try-catch 块来捕获和处理异常。
• 资源管理:使用 using 语句来确保 WebClient 实例在使用后被正确释放。
示例代码

using System;
using System.Net;

class WebClientExample
{
    static void Main(string[] args)
    {
        try
        {
            using (WebClient client = new WebClient())
            {
                // 下载字符串内容
                string response = client.DownloadString("https://api.example.com/data");
                Console.WriteLine("GET Response: " + response);

                // 上传字符串内容
                string uploadData = "{\"key\":\"value\"}";
                response = client.UploadString("https://api.example.com/post", uploadData);
                Console.WriteLine("POST Response: " + response);
            }
        }
        catch (WebException ex)
        {
            Console.WriteLine("Web Error: " + ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message);
        }
    }
}

3. HttpRequestMessage

HttpRequestMessage 用于构建 HTTP 请求,通常与 HttpClient 一起使用,提供更细粒度的控制。
注意
• 请求头设置:根据需要设置请求头,例如 Content-TypeAuthorization 等。
• 请求体设置:对于 POSTPUT 等请求,需要设置请求体内容。
• 响应处理:处理响应内容时,注意检查响应状态码和内容类型。
示例代码

using System;
using System.Net.Http;
using System.Threading.Tasks;

class HttpRequestMessageExample
{
    static async Task Main(string[] args)
    {
        using (HttpClient client = new HttpClient())
        {
            try
            {
                // 构建 GET 请求
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://api.example.com/data");
                HttpResponseMessage response = await client.SendAsync(request);
                response.EnsureSuccessStatusCode();
                string responseBody = await response.Content.ReadAsStringAsync();
                Console.WriteLine("GET Response: " + responseBody);

                // 构建 POST 请求
                request = new HttpRequestMessage(HttpMethod.Post, "https://api.example.com/post")
                {
                    Content = new StringContent("{\"key\":\"value\"}", System.Text.Encoding.UTF8, "application/json")
                };
                response = await client.SendAsync(request);
                response.EnsureSuccessStatusCode();
                responseBody = await response.Content.ReadAsStringAsync();
                Console.WriteLine("POST Response: " + responseBody);
            }
            catch (HttpRequestException ex)
            {
                Console.WriteLine("HTTP Error: " + ex.Message);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: " + ex.Message);
            }
        }
    }
}

4. HttpMessageHandler

HttpMessageHandler 是 HttpClient 的基础组件,用于处理 HTTP 请求和响应。通常情况下,开发者不需要直接使用 HttpMessageHandler,但在某些高级场景中,可以自定义消息处理器来实现特定的功能。

注意
• 自定义处理:在 SendAsync 方法中添加自定义逻辑,例如日志记录、请求拦截等。
• 资源管理:确保自定义的消息处理器在使用后被正确释放。
示例代码

using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

class CustomMessageHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        try
        {
            // 在发送请求之前添加自定义逻辑
            Console.WriteLine("Sending request to: " + request.RequestUri);

            // 调用基类的 SendAsync 方法
            HttpResponseMessage response = await base.SendAsync(request, cancellationToken);

            // 在接收响应之后添加自定义逻辑
            Console.WriteLine("Received response from: " + request.RequestUri);

            return response;
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error in message handler: " + ex.Message);
            throw;
        }
    }
}

class HttpMessageHandlerExample
{
    static async Task Main(string[] args)
    {
        try
        {
            // 创建自定义消息处理器
            CustomMessageHandler handler = new CustomMessageHandler();

            // 使用自定义消息处理器创建 HttpClient
            using (HttpClient client = new HttpClient(handler))
            {
                // 发送 GET 请求
                HttpResponseMessage response = await client.GetAsync("https://api.example.com/data");
                response.EnsureSuccessStatusCode();
                string responseBody = await response.Content.ReadAsStringAsync();
                Console.WriteLine("GET Response: " + responseBody);
            }
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine("HTTP Error: " + ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message);
        }
    }
}

总结
• HttpClient:现代、高效的 HTTP 客户端,支持异步操作,推荐使用;单例模式、异常处理、超时设置、取消请求。
• WebClient:较老的类,简单易用,但推荐使用 HttpClient;同步方法、异常处理、资源管理。
• HttpRequestMessage:用于构建 HTTP 请求,通常与 HttpClient 一起使用;请求头设置、请求体设置、响应处理。
• HttpMessageHandler:用于处理 HTTP 请求和响应,通常用于高级场景;:自定义处理、资源管理。

5.网络安全‌

C# 网络编程中有效地保护应用程序的安全。确保数据传输的安全性、正确处理用户输入、实施适当的身份验证和授权机制,以及遵循其他最佳实践,都是构建安全网络应用程序的关键步骤,包括SSL/TLS加密、密码安全存储、防止SQL注入、防止跨站脚本攻击(XSS)、防止跨站请求伪造(CSRF)、身份验证和授权等‌。

1. SSL/TLS 加密

使用 SSL/TLS 可以确保数据在传输过程中不被窃听或篡改。
示例:使用 HttpClient 进行 HTTPS 请求

using System;
using System.Net.Http;
using System.Threading.Tasks;

class HttpsExample
{
    static async Task Main(string[] args)
    {
        using (HttpClient client = new HttpClient())
        {
            try
            {
                HttpResponseMessage response = await client.GetAsync("https://api.example.com/data");
                response.EnsureSuccessStatusCode();
                string responseBody = await response.Content.ReadAsStringAsync();
                Console.WriteLine(responseBody);
            }
            catch (HttpRequestException e)
            {
                Console.WriteLine("\nException Caught!");
                Console.WriteLine("Message :{0} ", e.Message);
            }
        }
    }
}

2. 密码安全存储

使用哈希算法和盐值来安全地存储密码。
示例:使用 PasswordHasher 进行密码哈希

using Microsoft.AspNetCore.Identity;
using System;

class PasswordStorageExample
{
    static void Main(string[] args)
    {
        var passwordHasher = new PasswordHasher<string>();

        string password = "securePassword123";
        string hashedPassword = passwordHasher.HashPassword(null, password);
        Console.WriteLine("Hashed Password: " + hashedPassword);

        PasswordVerificationResult result = passwordHasher.VerifyHashedPassword(null, hashedPassword, password);
        Console.WriteLine("Verification Result: " + result);
    }
}

3. 防止 SQL 注入

使用参数化查询来防止 SQL 注入。
示例:使用 SqlCommand 进行参数化查询

using System;
using System.Data.SqlClient;

class SqlInjectionExample
{
    static void Main(string[] args)
    {
        string connectionString = "your_connection_string_here";
        string query = "SELECT * FROM Users WHERE Username = @Username AND Password = @Password";

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            SqlCommand command = new SqlCommand(query, connection);
            command.Parameters.AddWithValue("@Username", "user1");
            command.Parameters.AddWithValue("@Password", "pass1");

            connection.Open();
            SqlDataReader reader = command.ExecuteReader();

            while (reader.Read())
            {
                Console.WriteLine(reader["Username"]);
            }
        }
    }
}

4. 防止跨站脚本攻击 (XSS)

对用户输入进行适当的转义和验证。
示例:使用 HttpUtility.HtmlEncode 转义 HTML 内容

using System;
using System.Web;

class XssExample
{
    static void Main(string[] args)
    {
        string userInput = "<script>alert('XSS')</script>";
        string safeOutput = HttpUtility.HtmlEncode(userInput);
        Console.WriteLine("Safe Output: " + safeOutput);
    }
}

5. 防止跨站请求伪造 (CSRF)

使用 CSRF 令牌来防止跨站请求伪造。
示例:ASP.NET Core 中的 CSRF 保护
在 ASP.NET Core 中,CSRF 保护是默认启用的。确保在表单中包含 CSRF 令牌。

@model YourModel

<form method="post">
    @Html.AntiForgeryToken()
    <!-- Form fields here -->
    <button type="submit">Submit</button>
</form>

6. 身份验证和授权

使用身份验证和授权机制来保护应用程序。
示例:ASP.NET Core 中的身份验证和授权
Startup.cs 中配置身份验证和授权。

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        })
        .AddCookie();

        services.AddAuthorization();

        services.AddControllersWithViews();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

7. 其他安全措施

• 输入验证:对所有用户输入进行验证,确保其符合预期格式。
• 输出编码:对输出进行适当的编码,防止 XSS 攻击。
• 最小权限原则:确保应用程序以最小权限运行,限制不必要的权限。
• 定期更新和补丁:定期更新所有依赖库和框架,应用最新的安全补丁。
• 日志记录和监控:实施详细的日志记录和监控,以便及时发现和响应安全事件。

6.多线程与并发(待续)

• Thread 类:System.Threading.Thread 用于创建和管理线程。
• ThreadPool 类:System.Threading.ThreadPool 用于管理线程池。
• Task 并发:使用 Task.Run 和 Parallel 类进行并行任务处理。

7.序列化与反序列化(待续)

• JSON 序列化:使用 System.Text.Json.JsonSerializer 进行 JSON 序列化和反序列化。
• XML 序列化:使用 System.Xml.Serialization.XmlSerializer 进行 XML 序列化和反序列化。

8.网络配置(待续)

• 配置文件:使用 appsettings.json 或 app.config 配置网络参数。
• 环境变量:从环境变量中读取网络配置信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/934429.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

驱动---1.DAC8552实现三角波输出

最近开始进行新项目的研发&#xff0c;考虑用DAC做一个前级输出&#xff0c;选择了DAC8552这个器件的一个模块&#xff0c;用了野火的指南者做主控&#xff0c;芯片是STM32F103VET6&#xff0c;主频是72MHz。 一、器件手册重要信息提取 1.DAC8552具有十六位的分辨率、双通道输…

Elasticsearch入门之HTTP基础操作

RESTful REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。Web 应用程序最重要的 REST 原则是&#xff0c;客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在…

计算机启动过程 | Linux 启动流程

注&#xff1a;本文为“计算机启动、 Linux 启动”相关文章合辑。 替换引文部分不清晰的图。 探索计算机的启动过程 Aleksandr Goncharov 2023/04/21 很多人对计算机的启动方式很感兴趣。只要设备开启&#xff0c;这就是魔法开始和持续的地方。在本文中&#xff0c;我们将概…

【数据分享】1901-2023年我国省市县三级逐年最低气温数据(Shp/Excel格式)

之前我们分享过1901-2023年1km分辨率逐月最低气温栅格数据和Excel和Shp格式的省市县三级逐月最低气温数据&#xff0c;原始的逐月最低气温栅格数据来源于彭守璋学者在国家青藏高原科学数据中心平台上分享的数据&#xff01;基于逐月栅格数据我们采用求年平均值的方法得到逐年最…

Hash、HASHTABLE底层原理【Redis对象篇】

&#x1f3c6; 作者简介&#xff1a;席万里 ⚡ 个人网站&#xff1a;https://dahua.bloggo.chat/ ✍️ 一名后端开发小趴菜&#xff0c;同时略懂Vue与React前端技术&#xff0c;也了解一点微信小程序开发。 &#x1f37b; 对计算机充满兴趣&#xff0c;愿意并且希望学习更多的技…

YOLOv11改进,YOLOv11添加GSConv卷积+Slim-neck,助力小目标检测,二次创新C3k2结构

实时目标检测在工业和研究领域中具有重要意义。在边缘设备上,巨大的模型难以满足实时检测的要求,而由大量深度可分离卷积(depth-wise separable convolution)构建的轻量级模型又无法达到足够的精度。作者引入了一种新的轻量级卷积技术——GSConv,以减轻模型重量同时保持精…

利用Java爬虫MinC根据ID获取商品详情的完整指南

在当今数字化时代&#xff0c;获取商品详情数据对于市场分析、价格监控和竞争对手分析至关重要。Java作为一种强大且广泛使用的编程语言&#xff0c;非常适合开发复杂的爬虫系统。本文将详细介绍如何利用Java编写爬虫程序来根据商品ID获取商品详情&#xff0c;并提供完整的代码…

IP地址中的网络号:定义、作用与重要性

在计算机网络中&#xff0c;IP地址是每台设备的唯一标识。它由网络号和主机号两部分组成&#xff0c;其中网络号用于标识一个特定的网络&#xff0c;而主机号则用于区分该网络内的不同设备。网络号的正确分配和管理&#xff0c;是IP网络互联互通的基础。本文将带您走进网络号的…

java_连接数据库的方法_后端处理_前端调用_打通整体思路

参考&#xff1a;14 尚上优选项目-平台管理端-权限管理模块-开发角色管理接口&#xff08;上&#xff09;_哔哩哔哩_bilibili 第一步. 定义数据 在数据库中定义好数据&#xff08;如role表格&#xff09;&#xff0c;在java后端定义好对应的实体类&#xff08;Role类&#xf…

PHP富文本编辑器eWebEditor实战指南

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;eWebEditor是一个基于PHP的开源在线文本编辑器&#xff0c;提供类似Word的用户界面&#xff0c;简化了网页文本的创建和编辑过程。它广泛适用于博客、论坛、CMS等平台的内容管理&#xff0c;具备富文本编辑、表格…

docker nginx 部署vue 实例

1.安装docker https://blog.csdn.net/apgk1/article/details/144354588 2. 安装nginx docker 安装 nginx-CSDN博客 3. 复制 nginx-test 实例的一些文件到宿主机中&#xff0c;目前已 /home/jznh/路径演示 3.1 在/home/jznh/ 创建 conf html logs 三个文件夹&#xff0c;…

一个直接看央视频道的软件,可直接安装到TV

优点 打开无广告&#xff0c;直接自动默认打开央视频道加载速度快&#xff0c;切换频道响应快&#xff0c;不用转圈圈画质清晰&#xff0c;画质清晰无雪花频道多&#xff0c;差不多上百个频道 软件截图 下载链接 跳转原文下载

JavaEE之多线程的风险以及如何避免

上文我们了解了单线程以及线程的一些基本常见方法&#xff0c;但是多线程在一些方面会存在安全问题&#xff0c;此文我们来为多线程的安全 保驾护航&#xff01;&#xff01; 详情请见下文 1. 多线程带来的风险——线程安全 1.1 观察线程不安全 /*** 使用两个线程&#xff0c…

【OpenCV】直方图

理论 可以将直方图视为图形或曲线图&#xff0c;从而使您对图像的强度分布有一个整体的了解。它是在X轴上具有像素值(不总是从0到255的范围)&#xff0c;在Y轴上具有图像中相应像素数的图。 这只是理解图像的另一种方式。通过查看图像的直方图&#xff0c;您可以直观地了解该…

MoeCTF2024-Web题解

目录 1、弗拉格之地的入口 2、垫刀之路01: MoeCTF&#xff1f;启动&#xff01; 3、ez_http 4、ProveYourLove 5、弗拉格之地的挑战 6、ImageCloud前置 7、垫刀之路02: 普通的文件上传 8、垫刀之路03: 这是一个图床 9、垫刀之路05: 登陆网站 10、垫刀之路06: pop bas…

python学opencv|读取图像(六)读取图像像素RGB值

【1】引言 前序已经掌握了如何获取灰度图像的像素&#xff0c;文章链接为&#xff1a; python学opencv|读取图像&#xff08;五&#xff09;读取灰度图像像素-CSDN博客 实际上像素就像一个坐标轴&#xff0c;约束了图像的大小。 但实际上我们在学习过程中&#xff0c;对于同…

ThingsBoard规则链节点:RabbitMQ 节点详解

ThingsBoard 是一个开源的物联网平台&#xff0c;允许开发者快速构建IoT产品。它提供了设备连接、数据收集、处理和可视化等功能。为了实现高效的数据处理和消息传递&#xff0c;ThingsBoard 集成了多种消息队列服务&#xff0c;其中就包括了RabbitMQ。 RabbitMQ 是一个广泛使用…

如何创建基于udp的客户端和服务端

1.先创建好udpServer.hpp、udpServer.cc、udpClient.hpp、udpClient.cc的框架。 #pragma once #include <string> #include <iostream> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <cerrno> #include…

TCP 2

文章目录 Tcp状态三次握手四次挥手理解TIME WAIT状态 如上就是TCP连接管理部分 流量控制滑动窗口快重传 延迟应答原理 捎带应答总结TCP拥塞控制拥塞控制的策略 -- 每台识别主机拥塞的机器都要做 面向字节流和粘包问题tcp连接异常进程终止机器重启机器掉电/网线断开 Tcp状态 建…

ChatGPT Pro是什么

ChatGPT Pro 和 ChatGPT Plus 的区别主要体现在功能范围、适用场景和目标用户上。 ChatGPT Plus 功能 • 价格&#xff1a;20美元/月。 • 目标用户&#xff1a;针对个人用户设计。 • 主要特点&#xff1a; • 在高峰期响应速度更快。 • 使用高级模型&#xff08;如 GPT-4…