using System.Net; using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; using System.IO; // 為 Path 和 File 提供支持 using DBObj; using OverlayFormObj; namespace DualScreenDemo { public class TCPServer { private TcpListener listener; private const int Port = 1000; private readonly string hostNameSuffix; //private bool isProcessingCommand = false; public TCPServer() { listener = new TcpListener(IPAddress.Any, Port); hostNameSuffix = GetHostNameSuffix(); _ = Task.Run(() => Start()); } private bool IsFormReady(Form form) { if (form == null) return false; bool isReady = false; try { if (form.IsHandleCreated && !form.IsDisposed) { if (form.InvokeRequired) { form.Invoke(new Action(() => isReady = true)); } else { isReady = true; } } } catch { isReady = false; } return isReady; } private async Task SafeInvoke(Form form, Action action, int maxRetries = 10) { if (form == null) return; for (int i = 0; i < maxRetries; i++) { try { if (IsFormReady(form)) { if (form.InvokeRequired) { form.Invoke(action); } else { action(); } return; } } catch (Exception ex) { Console.WriteLine($"Invoke attempt {i + 1} failed: {ex.Message}"); } await Task.Delay(500); // 等待500毫秒后重试 } Console.WriteLine("Failed to invoke action after maximum retries"); } public void Start() { listener.Start(); Console.WriteLine("Server started on port " + Port + "."); // 心跳封包 //heartbeatSender sender = new heartbeatSender("127.0.0.1", 8888); //sender.Start(); // Console.WriteLine($"heart beat for server{sender.RemoteEndPoint.Address}:{sender.RemoteEndPoint.Port}"); try { while (true) { Console.WriteLine("Waiting for connections..."); using (TcpClient client = listener.AcceptTcpClient()) { Console.WriteLine("Connected!"); NetworkStream stream = client.GetStream(); while (client.Connected) { byte[] buffer = new byte[1024]; int bytesRead = stream.Read(buffer, 0, buffer.Length); if (bytesRead == 0) break; string request = Encoding.UTF8.GetString(buffer, 0, bytesRead); Console.WriteLine("Received: " + request.Trim()); if (request.Length < 5) { continue; } string requestHostSuffix = request.Substring(0, 3); string command = request.Substring(4); if (requestHostSuffix.Equals(hostNameSuffix, StringComparison.OrdinalIgnoreCase)) { // 新增監聽指令 if (command.Trim().Equals("X", StringComparison.OrdinalIgnoreCase)) { _ = SafeInvoke(VideoPlayerForm.Instance, async () => { Room.set("CLOSE"); try{ await HttpServer.RestartServer(); } catch (Exception ex) { Console.WriteLine("RestartServer 發生錯誤: " + ex.Message); } }); byte[] okResponse = Encoding.UTF8.GetBytes("OK\n"); stream.Write(okResponse, 0, okResponse.Length); continue; } if (command.Trim().Equals("O", StringComparison.OrdinalIgnoreCase)) { // 開台時跳至首頁 Room.set("OPEN"); byte[] okResponse = Encoding.UTF8.GetBytes("OK\n"); stream.Write(okResponse, 0, okResponse.Length); continue; } if (command.Trim().Equals("F", StringComparison.OrdinalIgnoreCase)) { _ = SafeInvoke(PrimaryForm.Instance, () => { Room.set("PAUSE"); }); byte[] okResponse = Encoding.UTF8.GetBytes("OK\n"); stream.Write(okResponse, 0, okResponse.Length); continue; } } if (IsFormReady(OverlayForm.MainForm)) { string message = request.Trim(); string pattern = @"^(全部|\d{4})\((白色|紅色|綠色|黑色|藍色)\)-"; Match match = Regex.Match(message, pattern); _ = SafeInvoke(OverlayForm.MainForm, () => { if (match.Success) { string marqueeMessage = message.Substring(match.Value.Length).Trim(); Color textColor = GetColorFromString(match.Groups[2].Value); OverlayForm.MainForm.UpdateMarqueeText(marqueeMessage, OverlayForm.MarqueeStartPosition.Right, textColor); } else { string marqueeMessage = "系統公告: " + message; OverlayForm.MainForm.UpdateMarqueeTextSecondLine(marqueeMessage); } }); byte[] okResponse = Encoding.UTF8.GetBytes("OK\n"); stream.Write(okResponse, 0, okResponse.Length); } /* if (request.Trim().Equals("exit", StringComparison.OrdinalIgnoreCase)) { break; } */ } //Console.WriteLine("Connection closed."); } } } catch (Exception e) { Console.WriteLine($"Error: {e.Message}"); } finally { listener.Stop(); } } private Color GetColorFromString(string colorName) { switch (colorName) { case "白色": return Color.White; case "紅色": return Color.Red; case "綠色": return Color.LightGreen; case "黑色": return Color.Black; case "藍色": return Color.LightBlue; default: return Color.Black; } } private string GetHostNameSuffix() { string hostName = Dns.GetHostName(); return hostName.Length > 3 ? hostName.Substring(hostName.Length - 3) : hostName; } } }