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

C# 即時應用開發實戰:TCP Socket 客戶端/伺服器架構基礎(一)

     編輯:關於C語言

專案概述

本實例展示 即時應用 架構:客戶端 (TcpClient) 與伺服器 (TcpServer) 透過 Socket 類別進行即時雙向通訊,並示範 ListView 控件在多執行緒環境下的安全更新、XML 格式資料傳輸。

核心架構

  • TcpServer.exe: 監聽 Port 8002,於獨立執行緒 (WaitingForClient) 接受連線,每連線建立專屬執行緒 (ReadSocket) 處理通訊,Socket 實例存於 Hashtable socketHolder,執行緒存於 threadHolder。
  • TcpClient.exe: 亦於獨立執行緒 (StartReceive) 讀取 Socket 資料,透過 MethodInvoker / BeginInvoke 安全更新 UI ListView。

伺服器啟動與監聽

Hashtable socketHolder = new Hashtable();
Hashtable threadHolder = new Hashtable();

public Form1() {
  InitializeComponent();
  tcpLsn = new TcpListener(8002);
  tcpLsn.Start();
  stpanel.Text = "Listen at: " + tcpLsn.LocalEndpoint.ToString();
  Thread tcpThd = new Thread(new ThreadStart(WaitingForClient));
  threadHolder.Add(connectId, tcpThd);
  tcpThd.Start();
}

客戶端連線與接收執行緒

private void menuConn_Click(object sender, EventArgs e) {
  ConnectDlg dlg = new ConnectDlg();
  if (dlg.ShowDialog(this) == DialogResult.OK) {
    s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    IPAddress host = IPAddress.Parse(dlg.IpAdd);
    int port = Int32.Parse(dlg.PortNum);
    IPEndPoint ep = new IPEndPoint(host, port);
    try {
      s.Connect(ep);
      if (s.Connected) {
        byte[] buf = ASCII.GetBytes(String.Format("{0}:{1}", dlg.UserName, dlg.PassWord));
        s.Send(buf, 0, buf.Length, 0); // 發送驗證封包
        t = new Thread(new ThreadStart(StartReceive));
        t.Start();
        sbar.Text = "Ready to receive data";
      }
    } catch (Exception ex) { MessageBox.Show(ex.ToString()); }
  }
}

private void StartReceive() {
  miv = new MethodInvoker(this.UpdateListView);
  int cnt = 0; string tmp = null; byte[] firstb = new byte[1];
  while (true) {
    try {
      byte[] receive = new byte[1];
      int ret = s.Receive(receive, 1, 0); // 逐位元組接收
      if (ret > 0) {
        switch (receive[0]) {
          case 11: cnt = 0; break; // VT 起始碼
          case 10: // LF 結束碼
            cnt = 0;
            if (firstb[0] == ':') HandleCommand(tmp);
            else if (firstb[0] == '<') HandleXML(tmp);
            else HandleText(tmp);
            tmp = null; break;
          default:
            if (cnt == 0) firstb[0] = receive[0];
            tmp += Encoding.ASCII.GetString(receive);
            cnt++; break;
        }
      }
    } catch (Exception ex) { if (!s.Connected) break; }
  }
  t.Abort();
}

協議設計:以 VT (0x0B) 為訊息起始、LF (0x0A) 為結束;首位元組判斷類型(: 指令、< XML、其他純文字),分派對應處理函數。

伺服器接受連線與執行緒管理

WaitingForClient 迴圈持續 AcceptSocket,建立連線 ID、儲存 Socket/執行緒至 HashTable、啟動 ReadSocket 執行緒,並在 UI ListView 顯示連線資訊。此為經典「一連線一執行緒」模型,適合中小規模即時應用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved