首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 網路程式設計:協議與檔案傳輸 (5) — 伺服器端協議處理與客戶端檔案傳送架構

     編輯:關於C語言

伺服器端關鍵點

  1. OnReadComplete() 中以委派非同步呼叫 handleProtocol(),因即將執行耗時的檔案讀寫操作。
  2. ProtocolHelper 與 FileProtocol 強型別設計極大簡化 XML 解析與型別轉換程式碼。
  3. handleProtocol() 依 FileRequestMode 分派:Send(客戶端傳送 → 伺服器接收)呼叫 receiveFile();Receive 暫時註解,留待後續實作。
  4. receiveFile():依協議中指定的 IP/Port 連回客戶端,以 1KB 緩衝區接收寫入檔案,檔名由 generateFileName() 產生時間相關隨機名稱。

客戶端實作:ServerClient 完整程式碼

先完成「發送檔案」功能,實際上是為 SendMessage() 增加姊妹方法 SendFile()。

class Client {
    static void Main(string[] args) {
        ConsoleKey key;
        ServerClient client = new ServerClient();
        string filePath = Environment.CurrentDirectory + "/Client01.jpg";
        if (File.Exists(filePath)) client.BeginSendFile(filePath);
        Console.WriteLine("\n\n輸入 \"Q\" 鍵退出。");
        do { key = Console.ReadKey(true).Key; } while (key != ConsoleKey.Q);
    }
}

public class ServerClient {
    private const int BufferSize = 8192;
    private byte[] buffer;
    private TcpClient client;
    private NetworkStream streamToServer;

    public ServerClient() {
        try {
            client = new TcpClient();
            client.Connect("localhost", 8500);
        } catch (Exception ex) {
            Console.WriteLine(ex.Message); return;
        }
        buffer = new byte[BufferSize];
        Console.WriteLine("Server Connected!{0} --> {1}",
            client.Client.LocalEndPoint, client.Client.RemoteEndPoint);
        streamToServer = client.GetStream();
    }

    // 發送控制協議訊息
    public void SendMessage(string msg) {
        byte[] temp = Encoding.Unicode.GetBytes(msg);
        try {
            lock (streamToServer) {
                streamToServer.Write(temp, 0, temp.Length);
            }
            Console.WriteLine("Sent: {0}", msg);
        } catch (Exception ex) {
            Console.WriteLine(ex.Message); return;
        }
    }

    // 非同步發送檔案進入點
    public void BeginSendFile(string filePath) {
        ParameterizedThreadStart start = new ParameterizedThreadStart(BeginSendFile);
        start.BeginInvoke(filePath, null, null);
    }

    private void BeginSendFile(object obj) { SendFile(obj as string); }

    // 同步發送檔案核心邏輯
    public void SendFile(string filePath) {
        IPAddress ip = IPAddress.Parse("127.0.0.1");
        TcpListener listener = new TcpListener(ip, 0); // 系統自動指派埠號
        listener.Start();
        int listeningPort = ((IPEndPoint)listener.LocalEndpoint).Port;

        // 組裝協議:檔名、模式、埠號
        string fileName = Path.GetFileName(filePath);
        FileProtocol protocol = new FileProtocol(FileRequestMode.Send, listeningPort, fileName);
        SendMessage(protocol.ToString()); // 發送協議給伺服器

        // 等待伺服器連回
        TcpClient localClient = listener.AcceptTcpClient();
        Console.WriteLine("Start sending file...");
        NetworkStream stream = localClient.GetStream();

        FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
        byte[] fileBuffer = new byte[1024]; // 每次 1KB
        int bytesRead, totalBytes = 0;
        SendStatus status = new SendStatus(filePath);

        try {
            do {
                Thread.Sleep(10); // 視覺效果暫停
                bytesRead = fs.Read(fileBuffer, 0, fileBuffer.Length);
                stream.Write(fileBuffer, 0, bytesRead);
                totalBytes += bytesRead;
                status.PrintStatus(totalBytes);
            } while (bytesRead > 0);
            Console.WriteLine("Total {0} bytes sent, Done!", totalBytes);
        } catch {
            Console.WriteLine("Server has lost...");
        } finally {
            stream.Dispose(); fs.Dispose(); localClient.Close(); listener.Stop();
        }
    }
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved