C# .NET Framework 4.0 网络编程完全指南

C# .NET Framework 4.0 网络编程完全指南

文档主要内容包括:

文件传输协议部分

FTP:使用.NET内置的FtpWebRequest类实现文件上传、下载和目录列表

SFTP/SCP:通过SSH.NET库实现安全文件传输(需要NuGet安装)

TFTP:自定义实现的简单文件传输协议

远程终端协议部分

Telnet:基于TcpClient的明文终端协议实现

SSH:使用SSH.NET库实现安全Shell连接和命令执行

Socket编程部分

原始Socket:展示了TCP服务器/客户端的完整实现,包括同步和异步操作

TcpClient类:使用高级封装类简化TCP通信

UDP编程:包括单播、广播和组播的实现

高级特性

连接池管理:提高性能的连接复用机制

心跳检测:保持连接活跃和故障检测

协议封装:自定义通信协议的设计和实现

特别说明:

所有代码都严格遵循.NET Framework 4.0标准,避免了字符串插值($)、null条件运算符(?.)等C# 6.0后的新语法

第三方库依赖:SFTP、SCP和SSH功能需要安装SSH.NET库(通过NuGet:Install-Package SSH.NET -Version 2016.1.0)

每个示例都包含:

完整的错误处理

资源释放机制

详细的中文注释

同步和异步操作示例

实用性强:代码可以直接复制使用,只需根据实际情况调整服务器地址、端口等参数

一、文件传输协议

1. FTP (File Transfer Protocol)

概述

FTP是用于在网络上进行文件传输的标准协议,工作在TCP/IP协议族的应用层,使用21端口进行控制连接,20端口进行数据传输。

实现方式
csharp 复制代码
using System;
using System.IO;
using System.Net;

public class FtpHelper
{
    private string ftpServer;
    private string userName;
    private string password;
    
    public FtpHelper(string server, string user, string pass)
    {
        this.ftpServer = server;
        this.userName = user;
        this.password = pass;
    }
    
    // 上传文件
    public bool UploadFile(string localFile, string remoteFile)
    {
        try
        {
            FileInfo fileInfo = new FileInfo(localFile);
            string uri = "ftp://" + ftpServer + "/" + remoteFile;
            
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);
            request.Method = WebRequestMethods.Ftp.UploadFile;
            request.Credentials = new NetworkCredential(userName, password);
            request.KeepAlive = false;
            request.UseBinary = true;
            request.ContentLength = fileInfo.Length;
            
            byte[] buffer = new byte[2048];
            int contentLen;
            
            using (FileStream fs = fileInfo.OpenRead())
            {
                using (Stream strm = request.GetRequestStream())
                {
                    contentLen = fs.Read(buffer, 0, buffer.Length);
                    while (contentLen != 0)
                    {
                        strm.Write(buffer, 0, contentLen);
                        contentLen = fs.Read(buffer, 0, buffer.Length);
                    }
                }
            }
            
            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            response.Close();
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("FTP上传失败: " + ex.Message);
            return false;
        }
    }
    
    // 下载文件
    public bool DownloadFile(string remoteFile, string localFile)
    {
        try
        {
            string uri = "ftp://" + ftpServer + "/" + remoteFile;
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);
            request.Method = WebRequestMethods.Ftp.DownloadFile;
            request.Credentials = new NetworkCredential(userName, password);
            
            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            Stream responseStream = response.GetResponseStream();
            
            using (FileStream fs = new FileStream(localFile, FileMode.Create))
            {
                byte[] buffer = new byte[2048];
                int read = 0;
                while ((read = responseStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    fs.Write(buffer, 0, read);
                }
            }
            
            responseStream.Close();
            response.Close();
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("FTP下载失败: " + ex.Message);
            return false;
        }
    }
    
    // 列出目录内容
    public string[] ListDirectory(string directory)
    {
        try
        {
            string uri = "ftp://" + ftpServer + "/" + directory;
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);
            request.Method = WebRequestMethods.Ftp.ListDirectory;
            request.Credentials = new NetworkCredential(userName, password);
            
            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream());
            
            string result = reader.ReadToEnd();
            reader.Close();
            response.Close();
            
            return result.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
        }
        catch (Exception ex)
        {
            Console.WriteLine("列出目录失败: " + ex.Message);
            return new string[0];
        }
    }
}

2. SFTP (SSH File Transfer Protocol)

概述

SFTP是基于SSH协议的安全文件传输协议,提供加密的文件传输功能。.NET Framework 4.0原生不支持SFTP,需要使用第三方库如SSH.NET

使用SSH.NET库实现(需通过NuGet安装)
csharp 复制代码
// 安装命令: Install-Package SSH.NET -Version 2016.1.0
using Renci.SshNet;
using System;
using System.IO;

public class SftpHelper
{
    private string host;
    private string username;
    private string password;
    private int port;
    
    public SftpHelper(string host, string username, string password, int port = 22)
    {
        this.host = host;
        this.username = username;
        this.password = password;
        this.port = port;
    }
    
    // 上传文件
    public bool UploadFile(string localPath, string remotePath)
    {
        try
        {
            using (SftpClient sftp = new SftpClient(host, port, username, password))
            {
                sftp.Connect();
                
                using (FileStream fs = new FileStream(localPath, FileMode.Open))
                {
                    sftp.UploadFile(fs, remotePath);
                }
                
                sftp.Disconnect();
            }
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("SFTP上传失败: " + ex.Message);
            return false;
        }
    }
    
    // 下载文件
    public bool DownloadFile(string remotePath, string localPath)
    {
        try
        {
            using (SftpClient sftp = new SftpClient(host, port, username, password))
            {
                sftp.Connect();
                
                using (FileStream fs = new FileStream(localPath, FileMode.Create))
                {
                    sftp.DownloadFile(remotePath, fs);
                }
                
                sftp.Disconnect();
            }
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("SFTP下载失败: " + ex.Message);
            return false;
        }
    }
}

3. SCP (Secure Copy Protocol)

概述

SCP是基于SSH协议的文件传输协议,用于在网络主机间安全地传输文件。同样需要使用SSH.NET库。

csharp 复制代码
using Renci.SshNet;
using System;

public class ScpHelper
{
    private string host;
    private string username;
    private string password;
    
    public ScpHelper(string host, string username, string password)
    {
        this.host = host;
        this.username = username;
        this.password = password;
    }
    
    // 上传文件
    public bool UploadFile(string localPath, string remotePath)
    {
        try
        {
            using (ScpClient scp = new ScpClient(host, username, password))
            {
                scp.Connect();
                scp.Upload(new System.IO.FileInfo(localPath), remotePath);
                scp.Disconnect();
            }
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("SCP上传失败: " + ex.Message);
            return false;
        }
    }
    
    // 下载文件
    public bool DownloadFile(string remotePath, string localPath)
    {
        try
        {
            using (ScpClient scp = new ScpClient(host, username, password))
            {
                scp.Connect();
                scp.Download(remotePath, new System.IO.DirectoryInfo(localPath));
                scp.Disconnect();
            }
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("SCP下载失败: " + ex.Message);
            return false;
        }
    }
}

4. TFTP (Trivial File Transfer Protocol)

概述

TFTP是一个简化的文件传输协议,基于UDP,通常用于网络设备的固件更新。需要自行实现或使用第三方库。

csharp 复制代码
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;

public class TftpClient
{
    private const int TFTP_PORT = 69;
    private const int BLOCK_SIZE = 512;
    
    // TFTP操作码
    private enum Opcode : ushort
    {
        RRQ = 1,    // 读请求
        WRQ = 2,    // 写请求
        DATA = 3,   // 数据包
        ACK = 4,    // 确认
        ERROR = 5   // 错误
    }
    
    private string serverAddress;
    private UdpClient udpClient;
    
    public TftpClient(string server)
    {
        this.serverAddress = server;
        this.udpClient = new UdpClient();
    }
    
    // 下载文件(简化版本)
    public bool DownloadFile(string remoteFile, string localFile)
    {
        try
        {
            IPEndPoint serverEP = new IPEndPoint(IPAddress.Parse(serverAddress), TFTP_PORT);
            
            // 构建RRQ请求
            byte[] request = BuildRequest(Opcode.RRQ, remoteFile, "octet");
            udpClient.Send(request, request.Length, serverEP);
            
            using (FileStream fs = new FileStream(localFile, FileMode.Create))
            {
                ushort blockNumber = 1;
                byte[] buffer;
                IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
                
                while (true)
                {
                    buffer = udpClient.Receive(ref remoteEP);
                    
                    if (buffer.Length >= 2)
                    {
                        ushort opcode = (ushort)((buffer[0] << 8) | buffer[1]);
                        
                        if (opcode == (ushort)Opcode.DATA)
                        {
                            ushort receivedBlock = (ushort)((buffer[2] << 8) | buffer[3]);
                            
                            if (receivedBlock == blockNumber)
                            {
                                int dataLength = buffer.Length - 4;
                                fs.Write(buffer, 4, dataLength);
                                
                                // 发送ACK
                                byte[] ack = BuildAck(blockNumber);
                                udpClient.Send(ack, ack.Length, remoteEP);
                                
                                if (dataLength < BLOCK_SIZE)
                                {
                                    break; // 传输完成
                                }
                                
                                blockNumber++;
                            }
                        }
                        else if (opcode == (ushort)Opcode.ERROR)
                        {
                            Console.WriteLine("TFTP错误");
                            return false;
                        }
                    }
                }
            }
            
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("TFTP下载失败: " + ex.Message);
            return false;
        }
    }
    
    private byte[] BuildRequest(Opcode opcode, string filename, string mode)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            // 操作码
            ms.WriteByte((byte)((ushort)opcode >> 8));
            ms.WriteByte((byte)((ushort)opcode & 0xFF));
            
            // 文件名
            byte[] filenameBytes = System.Text.Encoding.ASCII.GetBytes(filename);
            ms.Write(filenameBytes, 0, filenameBytes.Length);
            ms.WriteByte(0);
            
            // 模式
            byte[] modeBytes = System.Text.Encoding.ASCII.GetBytes(mode);
            ms.Write(modeBytes, 0, modeBytes.Length);
            ms.WriteByte(0);
            
            return ms.ToArray();
        }
    }
    
    private byte[] BuildAck(ushort blockNumber)
    {
        return new byte[] {
            0, (byte)Opcode.ACK,
            (byte)(blockNumber >> 8),
            (byte)(blockNumber & 0xFF)
        };
    }
}

二、远程终端协议

1. Telnet

概述

Telnet是一种网络协议,用于通过网络提供双向交互式文本通信。它是不安全的明文协议。

csharp 复制代码
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class TelnetClient
{
    private TcpClient tcpClient;
    private NetworkStream stream;
    private string host;
    private int port;
    
    public TelnetClient(string host, int port = 23)
    {
        this.host = host;
        this.port = port;
    }
    
    public bool Connect()
    {
        try
        {
            tcpClient = new TcpClient();
            tcpClient.Connect(host, port);
            stream = tcpClient.GetStream();
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("Telnet连接失败: " + ex.Message);
            return false;
        }
    }
    
    public void Send(string command)
    {
        if (stream != null && stream.CanWrite)
        {
            byte[] data = Encoding.ASCII.GetBytes(command + "\r\n");
            stream.Write(data, 0, data.Length);
            stream.Flush();
        }
    }
    
    public string Receive(int timeout = 1000)
    {
        if (stream != null && stream.CanRead)
        {
            StringBuilder sb = new StringBuilder();
            DateTime startTime = DateTime.Now;
            
            while ((DateTime.Now - startTime).TotalMilliseconds < timeout)
            {
                if (stream.DataAvailable)
                {
                    byte[] buffer = new byte[1024];
                    int bytesRead = stream.Read(buffer, 0, buffer.Length);
                    sb.Append(Encoding.ASCII.GetString(buffer, 0, bytesRead));
                }
                else
                {
                    Thread.Sleep(100);
                }
            }
            
            return sb.ToString();
        }
        return string.Empty;
    }
    
    public void Disconnect()
    {
        if (stream != null)
        {
            stream.Close();
        }
        if (tcpClient != null)
        {
            tcpClient.Close();
        }
    }
    
    // Telnet协商处理(简化版)
    private byte[] NegotiateOptions(byte[] data)
    {
        // IAC (Interpret As Command) = 255
        const byte IAC = 255;
        const byte DO = 253;
        const byte DONT = 254;
        const byte WILL = 251;
        const byte WONT = 252;
        
        for (int i = 0; i < data.Length; i++)
        {
            if (data[i] == IAC && i + 2 < data.Length)
            {
                byte command = data[i + 1];
                byte option = data[i + 2];
                
                // 简单的协商响应
                byte[] response = new byte[3];
                response[0] = IAC;
                
                if (command == DO)
                {
                    response[1] = WONT; // 拒绝所有选项
                }
                else if (command == WILL)
                {
                    response[1] = DONT; // 拒绝所有选项
                }
                
                response[2] = option;
                
                if (stream != null && stream.CanWrite)
                {
                    stream.Write(response, 0, 3);
                }
                
                i += 2; // 跳过已处理的字节
            }
        }
        
        return data;
    }
}

2. SSH (Secure Shell)

概述

SSH是一种加密的网络协议,用于在不安全的网络上安全地运行网络服务。使用SSH.NET库实现。

csharp 复制代码
using Renci.SshNet;
using System;

public class SshHelper
{
    private string host;
    private string username;
    private string password;
    private int port;
    private SshClient sshClient;
    
    public SshHelper(string host, string username, string password, int port = 22)
    {
        this.host = host;
        this.username = username;
        this.password = password;
        this.port = port;
    }
    
    // 连接到SSH服务器
    public bool Connect()
    {
        try
        {
            sshClient = new SshClient(host, port, username, password);
            sshClient.Connect();
            return sshClient.IsConnected;
        }
        catch (Exception ex)
        {
            Console.WriteLine("SSH连接失败: " + ex.Message);
            return false;
        }
    }
    
    // 执行单个命令
    public string ExecuteCommand(string command)
    {
        if (sshClient != null && sshClient.IsConnected)
        {
            try
            {
                SshCommand cmd = sshClient.CreateCommand(command);
                string result = cmd.Execute();
                
                if (!string.IsNullOrEmpty(cmd.Error))
                {
                    Console.WriteLine("命令错误: " + cmd.Error);
                }
                
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine("执行命令失败: " + ex.Message);
                return string.Empty;
            }
        }
        return string.Empty;
    }
    
    // 创建Shell会话(交互式)
    public void CreateShellSession()
    {
        if (sshClient != null && sshClient.IsConnected)
        {
            try
            {
                var shell = sshClient.CreateShellStream("xterm", 80, 24, 800, 600, 1024);
                
                // 读取欢迎信息
                string line = shell.ReadLine();
                while (!string.IsNullOrEmpty(line))
                {
                    Console.WriteLine(line);
                    line = shell.ReadLine();
                }
                
                // 交互式会话
                while (true)
                {
                    Console.Write("ssh> ");
                    string input = Console.ReadLine();
                    
                    if (input.ToLower() == "exit")
                        break;
                    
                    shell.WriteLine(input);
                    
                    // 读取响应
                    string response = shell.Read();
                    Console.WriteLine(response);
                }
                
                shell.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Shell会话失败: " + ex.Message);
            }
        }
    }
    
    // 断开连接
    public void Disconnect()
    {
        if (sshClient != null && sshClient.IsConnected)
        {
            sshClient.Disconnect();
        }
    }
    
    // 端口转发
    public void SetupPortForwarding(uint localPort, string remoteHost, uint remotePort)
    {
        if (sshClient != null && sshClient.IsConnected)
        {
            var forwarded = new ForwardedPortLocal("127.0.0.1", localPort, remoteHost, remotePort);
            sshClient.AddForwardedPort(forwarded);
            forwarded.Start();
            
            Console.WriteLine(string.Format("端口转发已建立: localhost:{0} -> {1}:{2}", 
                localPort, remoteHost, remotePort));
        }
    }
}

三、Socket编程

1. 原始Socket编程

TCP Socket服务器
csharp 复制代码
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class TcpSocketServer
{
    private Socket serverSocket;
    private int port;
    private bool isRunning;
    
    public TcpSocketServer(int port)
    {
        this.port = port;
    }
    
    public void Start()
    {
        try
        {
            // 创建Socket
            serverSocket = new Socket(AddressFamily.InterNetwork, 
                                    SocketType.Stream, 
                                    ProtocolType.Tcp);
            
            // 绑定端口
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, port);
            serverSocket.Bind(endPoint);
            
            // 开始监听
            serverSocket.Listen(10);
            isRunning = true;
            
            Console.WriteLine("服务器启动,监听端口: " + port);
            
            // 接受客户端连接
            Thread acceptThread = new Thread(AcceptClients);
            acceptThread.Start();
        }
        catch (Exception ex)
        {
            Console.WriteLine("服务器启动失败: " + ex.Message);
        }
    }
    
    private void AcceptClients()
    {
        while (isRunning)
        {
            try
            {
                Socket clientSocket = serverSocket.Accept();
                Console.WriteLine("客户端连接: " + clientSocket.RemoteEndPoint.ToString());
                
                // 为每个客户端创建新线程
                Thread clientThread = new Thread(HandleClient);
                clientThread.Start(clientSocket);
            }
            catch (Exception ex)
            {
                Console.WriteLine("接受客户端失败: " + ex.Message);
            }
        }
    }
    
    private void HandleClient(object clientObj)
    {
        Socket clientSocket = (Socket)clientObj;
        
        try
        {
            byte[] buffer = new byte[1024];
            
            while (clientSocket.Connected)
            {
                int received = clientSocket.Receive(buffer);
                
                if (received == 0)
                    break;
                
                string message = Encoding.UTF8.GetString(buffer, 0, received);
                Console.WriteLine("收到消息: " + message);
                
                // 回显消息
                string response = "服务器收到: " + message;
                byte[] responseData = Encoding.UTF8.GetBytes(response);
                clientSocket.Send(responseData);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("处理客户端失败: " + ex.Message);
        }
        finally
        {
            clientSocket.Close();
        }
    }
    
    public void Stop()
    {
        isRunning = false;
        if (serverSocket != null)
        {
            serverSocket.Close();
        }
    }
}
TCP Socket客户端
csharp 复制代码
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class TcpSocketClient
{
    private Socket clientSocket;
    private string serverAddress;
    private int port;
    
    public TcpSocketClient(string server, int port)
    {
        this.serverAddress = server;
        this.port = port;
    }
    
    public bool Connect()
    {
        try
        {
            clientSocket = new Socket(AddressFamily.InterNetwork, 
                                    SocketType.Stream, 
                                    ProtocolType.Tcp);
            
            IPEndPoint serverEP = new IPEndPoint(IPAddress.Parse(serverAddress), port);
            clientSocket.Connect(serverEP);
            
            Console.WriteLine("连接到服务器: " + serverEP.ToString());
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("连接失败: " + ex.Message);
            return false;
        }
    }
    
    public void Send(string message)
    {
        if (clientSocket != null && clientSocket.Connected)
        {
            byte[] data = Encoding.UTF8.GetBytes(message);
            clientSocket.Send(data);
        }
    }
    
    public string Receive()
    {
        if (clientSocket != null && clientSocket.Connected)
        {
            byte[] buffer = new byte[1024];
            int received = clientSocket.Receive(buffer);
            return Encoding.UTF8.GetString(buffer, 0, received);
        }
        return string.Empty;
    }
    
    // 异步发送
    public void SendAsync(string message)
    {
        if (clientSocket != null && clientSocket.Connected)
        {
            byte[] data = Encoding.UTF8.GetBytes(message);
            clientSocket.BeginSend(data, 0, data.Length, SocketFlags.None, 
                new AsyncCallback(SendCallback), clientSocket);
        }
    }
    
    private void SendCallback(IAsyncResult ar)
    {
        try
        {
            Socket socket = (Socket)ar.AsyncState;
            int bytesSent = socket.EndSend(ar);
            Console.WriteLine("异步发送了 " + bytesSent + " 字节");
        }
        catch (Exception ex)
        {
            Console.WriteLine("异步发送失败: " + ex.Message);
        }
    }
    
    // 异步接收
    public void ReceiveAsync()
    {
        if (clientSocket != null && clientSocket.Connected)
        {
            StateObject state = new StateObject();
            state.workSocket = clientSocket;
            
            clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 
                SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
        }
    }
    
    private void ReceiveCallback(IAsyncResult ar)
    {
        try
        {
            StateObject state = (StateObject)ar.AsyncState;
            Socket socket = state.workSocket;
            
            int bytesRead = socket.EndReceive(ar);
            
            if (bytesRead > 0)
            {
                string message = Encoding.UTF8.GetString(state.buffer, 0, bytesRead);
                Console.WriteLine("异步接收: " + message);
                
                // 继续接收
                socket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 
                    SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("异步接收失败: " + ex.Message);
        }
    }
    
    public void Disconnect()
    {
        if (clientSocket != null && clientSocket.Connected)
        {
            clientSocket.Shutdown(SocketShutdown.Both);
            clientSocket.Close();
        }
    }
    
    // 状态对象
    public class StateObject
    {
        public Socket workSocket = null;
        public const int BufferSize = 1024;
        public byte[] buffer = new byte[BufferSize];
    }
}

2. TcpClient类

TcpClient服务器(使用TcpListener)
csharp 复制代码
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class TcpServer
{
    private TcpListener listener;
    private int port;
    private bool isRunning;
    
    public TcpServer(int port)
    {
        this.port = port;
    }
    
    public void Start()
    {
        try
        {
            listener = new TcpListener(IPAddress.Any, port);
            listener.Start();
            isRunning = true;
            
            Console.WriteLine("TCP服务器启动,端口: " + port);
            
            Thread listenThread = new Thread(ListenForClients);
            listenThread.Start();
        }
        catch (Exception ex)
        {
            Console.WriteLine("服务器启动失败: " + ex.Message);
        }
    }
    
    private void ListenForClients()
    {
        while (isRunning)
        {
            try
            {
                TcpClient client = listener.AcceptTcpClient();
                Console.WriteLine("客户端连接: " + client.Client.RemoteEndPoint.ToString());
                
                Thread clientThread = new Thread(HandleClientComm);
                clientThread.Start(client);
            }
            catch (Exception ex)
            {
                Console.WriteLine("接受客户端失败: " + ex.Message);
            }
        }
    }
    
    private void HandleClientComm(object client)
    {
        TcpClient tcpClient = (TcpClient)client;
        NetworkStream clientStream = tcpClient.GetStream();
        
        byte[] message = new byte[4096];
        int bytesRead;
        
        while (true)
        {
            bytesRead = 0;
            
            try
            {
                bytesRead = clientStream.Read(message, 0, 4096);
            }
            catch
            {
                break;
            }
            
            if (bytesRead == 0)
            {
                break;
            }
            
            string receivedMessage = Encoding.UTF8.GetString(message, 0, bytesRead);
            Console.WriteLine("收到: " + receivedMessage);
            
            // 发送响应
            string response = "服务器响应: " + receivedMessage;
            byte[] responseData = Encoding.UTF8.GetBytes(response);
            clientStream.Write(responseData, 0, responseData.Length);
            clientStream.Flush();
        }
        
        tcpClient.Close();
    }
    
    public void Stop()
    {
        isRunning = false;
        if (listener != null)
        {
            listener.Stop();
        }
    }
}
TcpClient客户端
csharp 复制代码
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;

public class TcpClientHelper
{
    private TcpClient client;
    private NetworkStream stream;
    private string serverAddress;
    private int port;
    
    public TcpClientHelper(string server, int port)
    {
        this.serverAddress = server;
        this.port = port;
    }
    
    public bool Connect()
    {
        try
        {
            client = new TcpClient();
            client.Connect(serverAddress, port);
            stream = client.GetStream();
            
            Console.WriteLine("连接成功");
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("连接失败: " + ex.Message);
            return false;
        }
    }
    
    public void Send(string message)
    {
        if (stream != null && stream.CanWrite)
        {
            byte[] data = Encoding.UTF8.GetBytes(message);
            stream.Write(data, 0, data.Length);
            stream.Flush();
        }
    }
    
    public string Receive()
    {
        if (stream != null && stream.CanRead)
        {
            byte[] buffer = new byte[1024];
            int bytesRead = stream.Read(buffer, 0, buffer.Length);
            return Encoding.UTF8.GetString(buffer, 0, bytesRead);
        }
        return string.Empty;
    }
    
    // 使用StreamReader和StreamWriter
    public void SendWithWriter(string message)
    {
        if (stream != null)
        {
            StreamWriter writer = new StreamWriter(stream, Encoding.UTF8);
            writer.WriteLine(message);
            writer.Flush();
        }
    }
    
    public string ReceiveWithReader()
    {
        if (stream != null)
        {
            StreamReader reader = new StreamReader(stream, Encoding.UTF8);
            return reader.ReadLine();
        }
        return string.Empty;
    }
    
    // 异步操作
    public void SendAsync(string message)
    {
        if (stream != null && stream.CanWrite)
        {
            byte[] data = Encoding.UTF8.GetBytes(message);
            stream.BeginWrite(data, 0, data.Length, 
                new AsyncCallback(WriteCallback), stream);
        }
    }
    
    private void WriteCallback(IAsyncResult ar)
    {
        try
        {
            NetworkStream stream = (NetworkStream)ar.AsyncState;
            stream.EndWrite(ar);
            Console.WriteLine("异步发送完成");
        }
        catch (Exception ex)
        {
            Console.WriteLine("异步发送失败: " + ex.Message);
        }
    }
    
    public void Disconnect()
    {
        if (stream != null)
        {
            stream.Close();
        }
        if (client != null)
        {
            client.Close();
        }
    }
}

3. UDP编程

UDP服务器
csharp 复制代码
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class UdpServer
{
    private UdpClient udpServer;
    private int port;
    private bool isRunning;
    private Thread receiveThread;
    
    public UdpServer(int port)
    {
        this.port = port;
    }
    
    public void Start()
    {
        try
        {
            udpServer = new UdpClient(port);
            isRunning = true;
            
            Console.WriteLine("UDP服务器启动,端口: " + port);
            
            receiveThread = new Thread(ReceiveData);
            receiveThread.Start();
        }
        catch (Exception ex)
        {
            Console.WriteLine("UDP服务器启动失败: " + ex.Message);
        }
    }
    
    private void ReceiveData()
    {
        IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
        
        while (isRunning)
        {
            try
            {
                byte[] data = udpServer.Receive(ref remoteEP);
                string message = Encoding.UTF8.GetString(data);
                
                Console.WriteLine("收到来自 " + remoteEP.ToString() + " 的消息: " + message);
                
                // 发送响应
                string response = "UDP服务器收到: " + message;
                byte[] responseData = Encoding.UTF8.GetBytes(response);
                udpServer.Send(responseData, responseData.Length, remoteEP);
            }
            catch (Exception ex)
            {
                if (isRunning)
                {
                    Console.WriteLine("接收数据失败: " + ex.Message);
                }
            }
        }
    }
    
    // 广播消息
    public void Broadcast(string message)
    {
        if (udpServer != null)
        {
            byte[] data = Encoding.UTF8.GetBytes(message);
            IPEndPoint broadcastEP = new IPEndPoint(IPAddress.Broadcast, port);
            udpServer.Send(data, data.Length, broadcastEP);
        }
    }
    
    // 组播支持
    public void JoinMulticastGroup(string multicastIP)
    {
        try
        {
            IPAddress multicastAddress = IPAddress.Parse(multicastIP);
            udpServer.JoinMulticastGroup(multicastAddress);
            Console.WriteLine("加入组播组: " + multicastIP);
        }
        catch (Exception ex)
        {
            Console.WriteLine("加入组播组失败: " + ex.Message);
        }
    }
    
    public void Stop()
    {
        isRunning = false;
        if (udpServer != null)
        {
            udpServer.Close();
        }
        if (receiveThread != null)
        {
            receiveThread.Join(1000);
        }
    }
}
UDP客户端
csharp 复制代码
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class UdpClientHelper
{
    private UdpClient udpClient;
    private string serverAddress;
    private int port;
    private Thread receiveThread;
    private bool isListening;
    
    public UdpClientHelper(string server, int port)
    {
        this.serverAddress = server;
        this.port = port;
        this.udpClient = new UdpClient();
    }
    
    public void Send(string message)
    {
        try
        {
            byte[] data = Encoding.UTF8.GetBytes(message);
            IPEndPoint serverEP = new IPEndPoint(IPAddress.Parse(serverAddress), port);
            udpClient.Send(data, data.Length, serverEP);
            Console.WriteLine("发送消息: " + message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("发送失败: " + ex.Message);
        }
    }
    
    public void StartListening()
    {
        isListening = true;
        receiveThread = new Thread(ReceiveData);
        receiveThread.Start();
    }
    
    private void ReceiveData()
    {
        IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
        
        while (isListening)
        {
            try
            {
                byte[] data = udpClient.Receive(ref remoteEP);
                string message = Encoding.UTF8.GetString(data);
                Console.WriteLine("收到消息: " + message);
                
                // 触发事件或处理消息
                OnMessageReceived(message, remoteEP);
            }
            catch (Exception ex)
            {
                if (isListening)
                {
                    Console.WriteLine("接收失败: " + ex.Message);
                }
            }
        }
    }
    
    // 异步发送
    public void SendAsync(string message)
    {
        try
        {
            byte[] data = Encoding.UTF8.GetBytes(message);
            IPEndPoint serverEP = new IPEndPoint(IPAddress.Parse(serverAddress), port);
            
            udpClient.BeginSend(data, data.Length, serverEP, 
                new AsyncCallback(SendCallback), udpClient);
        }
        catch (Exception ex)
        {
            Console.WriteLine("异步发送失败: " + ex.Message);
        }
    }
    
    private void SendCallback(IAsyncResult ar)
    {
        try
        {
            UdpClient client = (UdpClient)ar.AsyncState;
            int bytesSent = client.EndSend(ar);
            Console.WriteLine("异步发送了 " + bytesSent + " 字节");
        }
        catch (Exception ex)
        {
            Console.WriteLine("发送回调失败: " + ex.Message);
        }
    }
    
    // 异步接收
    public void ReceiveAsync()
    {
        udpClient.BeginReceive(new AsyncCallback(ReceiveCallback), udpClient);
    }
    
    private void ReceiveCallback(IAsyncResult ar)
    {
        try
        {
            UdpClient client = (UdpClient)ar.AsyncState;
            IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
            
            byte[] data = client.EndReceive(ar, ref remoteEP);
            string message = Encoding.UTF8.GetString(data);
            
            Console.WriteLine("异步收到: " + message);
            
            // 继续接收
            client.BeginReceive(new AsyncCallback(ReceiveCallback), client);
        }
        catch (Exception ex)
        {
            Console.WriteLine("接收回调失败: " + ex.Message);
        }
    }
    
    protected virtual void OnMessageReceived(string message, IPEndPoint sender)
    {
        // 可以在这里触发事件或处理消息
    }
    
    public void StopListening()
    {
        isListening = false;
        if (receiveThread != null)
        {
            receiveThread.Join(1000);
        }
    }
    
    public void Close()
    {
        StopListening();
        if (udpClient != null)
        {
            udpClient.Close();
        }
    }
}

四、高级特性和最佳实践

1. 连接池管理

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;

public class TcpConnectionPool
{
    private Queue<TcpClient> availableConnections;
    private List<TcpClient> allConnections;
    private string serverAddress;
    private int port;
    private int maxPoolSize;
    private int minPoolSize;
    private object lockObject = new object();
    
    public TcpConnectionPool(string server, int port, int minSize, int maxSize)
    {
        this.serverAddress = server;
        this.port = port;
        this.minPoolSize = minSize;
        this.maxPoolSize = maxSize;
        
        availableConnections = new Queue<TcpClient>();
        allConnections = new List<TcpClient>();
        
        InitializePool();
    }
    
    private void InitializePool()
    {
        lock (lockObject)
        {
            for (int i = 0; i < minPoolSize; i++)
            {
                TcpClient client = CreateConnection();
                if (client != null)
                {
                    availableConnections.Enqueue(client);
                    allConnections.Add(client);
                }
            }
        }
    }
    
    private TcpClient CreateConnection()
    {
        try
        {
            TcpClient client = new TcpClient();
            client.Connect(serverAddress, port);
            return client;
        }
        catch (Exception ex)
        {
            Console.WriteLine("创建连接失败: " + ex.Message);
            return null;
        }
    }
    
    public TcpClient GetConnection()
    {
        lock (lockObject)
        {
            if (availableConnections.Count > 0)
            {
                TcpClient client = availableConnections.Dequeue();
                
                // 检查连接是否有效
                if (client.Connected)
                {
                    return client;
                }
                else
                {
                    allConnections.Remove(client);
                    return GetConnection(); // 递归获取新连接
                }
            }
            else if (allConnections.Count < maxPoolSize)
            {
                // 创建新连接
                TcpClient newClient = CreateConnection();
                if (newClient != null)
                {
                    allConnections.Add(newClient);
                    return newClient;
                }
            }
        }
        
        // 等待可用连接
        Thread.Sleep(100);
        return GetConnection();
    }
    
    public void ReturnConnection(TcpClient client)
    {
        lock (lockObject)
        {
            if (client != null && client.Connected)
            {
                availableConnections.Enqueue(client);
            }
            else
            {
                allConnections.Remove(client);
            }
        }
    }
    
    public void CloseAllConnections()
    {
        lock (lockObject)
        {
            foreach (TcpClient client in allConnections)
            {
                try
                {
                    client.Close();
                }
                catch { }
            }
            
            availableConnections.Clear();
            allConnections.Clear();
        }
    }
}

2. 心跳检测机制

csharp 复制代码
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class HeartbeatClient
{
    private TcpClient client;
    private NetworkStream stream;
    private Timer heartbeatTimer;
    private DateTime lastHeartbeat;
    private int heartbeatInterval = 30000; // 30秒
    private int heartbeatTimeout = 60000; // 60秒超时
    
    public bool IsConnected 
    { 
        get 
        { 
            return client != null && client.Connected; 
        } 
    }
    
    public void Connect(string server, int port)
    {
        client = new TcpClient();
        client.Connect(server, port);
        stream = client.GetStream();
        
        // 启动心跳
        heartbeatTimer = new Timer(SendHeartbeat, null, 0, heartbeatInterval);
        lastHeartbeat = DateTime.Now;
        
        // 启动接收线程
        Thread receiveThread = new Thread(ReceiveData);
        receiveThread.Start();
    }
    
    private void SendHeartbeat(object state)
    {
        try
        {
            if (IsConnected)
            {
                // 检查超时
                TimeSpan timeSinceLastHeartbeat = DateTime.Now - lastHeartbeat;
                if (timeSinceLastHeartbeat.TotalMilliseconds > heartbeatTimeout)
                {
                    Console.WriteLine("心跳超时,重新连接");
                    Reconnect();
                    return;
                }
                
                // 发送心跳包
                byte[] heartbeatData = Encoding.UTF8.GetBytes("HEARTBEAT");
                stream.Write(heartbeatData, 0, heartbeatData.Length);
                stream.Flush();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("心跳发送失败: " + ex.Message);
            Reconnect();
        }
    }
    
    private void ReceiveData()
    {
        byte[] buffer = new byte[1024];
        
        while (IsConnected)
        {
            try
            {
                int bytesRead = stream.Read(buffer, 0, buffer.Length);
                if (bytesRead > 0)
                {
                    string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                    
                    if (message == "HEARTBEAT_ACK")
                    {
                        lastHeartbeat = DateTime.Now;
                    }
                    else
                    {
                        // 处理其他消息
                        ProcessMessage(message);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("接收数据失败: " + ex.Message);
                break;
            }
        }
    }
    
    private void ProcessMessage(string message)
    {
        Console.WriteLine("收到消息: " + message);
    }
    
    private void Reconnect()
    {
        // 实现重连逻辑
        Console.WriteLine("尝试重新连接...");
    }
    
    public void Disconnect()
    {
        if (heartbeatTimer != null)
        {
            heartbeatTimer.Dispose();
        }
        
        if (stream != null)
        {
            stream.Close();
        }
        
        if (client != null)
        {
            client.Close();
        }
    }
}

3. 数据传输协议封装

csharp 复制代码
using System;
using System.IO;
using System.Text;

// 自定义协议包
public class ProtocolPacket
{
    public byte Header { get; set; }      // 包头标识
    public ushort Length { get; set; }    // 数据长度
    public byte Command { get; set; }     // 命令类型
    public byte[] Data { get; set; }      // 数据内容
    public byte Checksum { get; set; }    // 校验和
    
    public const byte HEADER = 0xAA;      // 固定包头
    
    // 命令类型定义
    public class Commands
    {
        public const byte LOGIN = 0x01;
        public const byte LOGOUT = 0x02;
        public const byte MESSAGE = 0x03;
        public const byte FILE_TRANSFER = 0x04;
        public const byte HEARTBEAT = 0x05;
    }
    
    // 将包序列化为字节数组
    public byte[] ToBytes()
    {
        using (MemoryStream ms = new MemoryStream())
        {
            ms.WriteByte(HEADER);
            
            // 写入长度(大端序)
            ms.WriteByte((byte)(Length >> 8));
            ms.WriteByte((byte)(Length & 0xFF));
            
            ms.WriteByte(Command);
            
            if (Data != null && Data.Length > 0)
            {
                ms.Write(Data, 0, Data.Length);
            }
            
            // 计算校验和
            byte[] buffer = ms.ToArray();
            Checksum = CalculateChecksum(buffer);
            ms.WriteByte(Checksum);
            
            return ms.ToArray();
        }
    }
    
    // 从字节数组解析包
    public static ProtocolPacket FromBytes(byte[] buffer)
    {
        if (buffer == null || buffer.Length < 5)
            return null;
        
        ProtocolPacket packet = new ProtocolPacket();
        
        using (MemoryStream ms = new MemoryStream(buffer))
        {
            packet.Header = (byte)ms.ReadByte();
            
            if (packet.Header != HEADER)
                return null;
            
            // 读取长度
            byte highByte = (byte)ms.ReadByte();
            byte lowByte = (byte)ms.ReadByte();
            packet.Length = (ushort)((highByte << 8) | lowByte);
            
            packet.Command = (byte)ms.ReadByte();
            
            // 读取数据
            if (packet.Length > 0)
            {
                packet.Data = new byte[packet.Length];
                ms.Read(packet.Data, 0, packet.Length);
            }
            
            packet.Checksum = (byte)ms.ReadByte();
            
            // 验证校验和
            byte calculatedChecksum = CalculateChecksum(buffer, buffer.Length - 1);
            if (calculatedChecksum != packet.Checksum)
            {
                Console.WriteLine("校验和错误");
                return null;
            }
        }
        
        return packet;
    }
    
    // 计算校验和
    private static byte CalculateChecksum(byte[] data, int length = -1)
    {
        if (length == -1)
            length = data.Length;
        
        byte checksum = 0;
        for (int i = 0; i < length; i++)
        {
            checksum ^= data[i];
        }
        return checksum;
    }
    
    // 创建消息包
    public static ProtocolPacket CreateMessage(string message)
    {
        byte[] data = Encoding.UTF8.GetBytes(message);
        return new ProtocolPacket
        {
            Command = Commands.MESSAGE,
            Data = data,
            Length = (ushort)data.Length
        };
    }
    
    // 创建心跳包
    public static ProtocolPacket CreateHeartbeat()
    {
        return new ProtocolPacket
        {
            Command = Commands.HEARTBEAT,
            Data = new byte[0],
            Length = 0
        };
    }
}

// 协议处理器
public class ProtocolHandler
{
    private byte[] receiveBuffer = new byte[4096];
    private int bufferOffset = 0;
    
    public void ProcessReceivedData(byte[] data, int length)
    {
        // 将新数据添加到缓冲区
        Array.Copy(data, 0, receiveBuffer, bufferOffset, length);
        bufferOffset += length;
        
        // 尝试解析包
        while (bufferOffset >= 5) // 最小包长度
        {
            // 查找包头
            int headerIndex = -1;
            for (int i = 0; i < bufferOffset; i++)
            {
                if (receiveBuffer[i] == ProtocolPacket.HEADER)
                {
                    headerIndex = i;
                    break;
                }
            }
            
            if (headerIndex == -1)
            {
                // 没有找到包头,清空缓冲区
                bufferOffset = 0;
                return;
            }
            
            // 移动数据到缓冲区开始
            if (headerIndex > 0)
            {
                Array.Copy(receiveBuffer, headerIndex, receiveBuffer, 0, bufferOffset - headerIndex);
                bufferOffset -= headerIndex;
            }
            
            // 检查是否有完整的包
            if (bufferOffset < 3)
                return;
            
            ushort packetLength = (ushort)((receiveBuffer[1] << 8) | receiveBuffer[2]);
            int totalPacketSize = 5 + packetLength; // 头(1) + 长度(2) + 命令(1) + 数据 + 校验(1)
            
            if (bufferOffset < totalPacketSize)
                return; // 包不完整
            
            // 提取完整的包
            byte[] packetData = new byte[totalPacketSize];
            Array.Copy(receiveBuffer, 0, packetData, 0, totalPacketSize);
            
            // 解析包
            ProtocolPacket packet = ProtocolPacket.FromBytes(packetData);
            if (packet != null)
            {
                HandlePacket(packet);
            }
            
            // 移除已处理的数据
            Array.Copy(receiveBuffer, totalPacketSize, receiveBuffer, 0, bufferOffset - totalPacketSize);
            bufferOffset -= totalPacketSize;
        }
    }
    
    private void HandlePacket(ProtocolPacket packet)
    {
        switch (packet.Command)
        {
            case ProtocolPacket.Commands.MESSAGE:
                string message = Encoding.UTF8.GetString(packet.Data);
                Console.WriteLine("收到消息: " + message);
                break;
                
            case ProtocolPacket.Commands.HEARTBEAT:
                Console.WriteLine("收到心跳包");
                break;
                
            default:
                Console.WriteLine("未知命令: " + packet.Command);
                break;
        }
    }
}

五、注意事项和最佳实践

性能优化

  1. 使用异步操作:避免阻塞主线程,提高并发处理能力
  2. 连接池:复用连接,减少创建和销毁连接的开销
  3. 缓冲区管理:合理设置缓冲区大小,避免频繁的内存分配
  4. 批量处理:尽可能批量发送数据,减少网络往返次数

安全考虑

  1. 使用加密协议:优先使用SFTP、SSH等加密协议
  2. 身份验证:实现强身份验证机制
  3. 输入验证:对所有输入数据进行验证和清理
  4. 超时设置:设置合理的连接和操作超时时间

错误处理

  1. 异常捕获:全面的异常处理机制
  2. 重试机制:实现自动重连和重试逻辑
  3. 日志记录:记录关键操作和错误信息
  4. 资源清理:确保在finally块中释放资源

兼容性注意

  1. 本文档所有代码示例都基于.NET Framework 4.0
  2. 避免使用C# 6.0及以后的新特性(如字符串插值、null条件运算符等)
  3. 某些功能(如SFTP、SSH)需要第三方库支持
  4. 注意不同操作系统的网络配置差异
相关推荐
MicrosoftReactor11 分钟前
技术速递|使用 AI 应用模板扩展创建一个 .NET AI 应用与自定义数据进行对话
人工智能·.net
★YUI★2 小时前
学习游戏制作记录(保存装备物品技能树和删除存档文件)8.26
学习·游戏·unity·c#
爱炸薯条的小朋友2 小时前
C#由Dictionary不正确释放造成的内存泄漏问题与GC代系
开发语言·opencv·c#
小白白3 小时前
局域网共享文件夹
网络
Twinkle1754 小时前
linux下的网络编程:TCP(传输控制协议)编程
linux·网络·tcp/ip
许泽宇的技术分享6 小时前
当自然语言遇上数据库:Text2Sql.Net的MCP革命如何重新定义开发者与数据的交互方式
数据库·.net·text2sql·mcp
源远流长jerry6 小时前
STM32之DMA详解
linux·网络·c++·stm32·单片机·嵌入式硬件
wanhengidc6 小时前
云手机会占用本地手机内存吗?
运维·服务器·网络·安全·智能手机
北极光SD-WAN组网6 小时前
大型电动化工程机械设备智能施工试验场的网络设计方案
网络