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