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

C# 即時應用開發實戰:TCP 伺服器多執行緒連線管理與資料載入廣播(二)

     編輯:關於C語言

伺服器等待客戶端連線主迴圈

public void WaitingForClient() {
  while (true) {
    Socket sckt = tcpLsn.AcceptSocket(); // 阻塞等待連線
    if (connectId < 10000) Interlocked.Increment(ref connectId);
    else connectId = 1;

    if (socketHolder.Count < MaxConnected) {
      while (socketHolder.Contains(connectId))
        Interlocked.Increment(ref connectId);

      Thread td = new Thread(new ThreadStart(ReadSocket));
      lock (this) {
        socketHolder.Add(connectId, sckt);   // 保存連線 Socket
        threadHolder.Add(connectId, td);     // 保存處理執行緒
      }
      td.Start();
    }
  }
}

要點:Interlocked.Increment 確保連線 ID 原子性遞增;lock 保護 HashTable 多執行緒存取;每連線建立專屬執行緒處理通訊。

客戶端通訊處理執行緒

public void ReadSocket() {
  long realId = connectId; // 捕獲啟動時的 ID
  int ind = -1;
  Socket s = (Socket)socketHolder[realId];

  while (true) {
    if (s.Connected) {
      Byte[] receive = new Byte[37];
      try {
        int ret = s.Receive(receive, receive.Length, 0); // 阻塞接收
        if (ret > 0) {
          string tmp = Encoding.ASCII.GetString(receive);
          if (tmp.Length > 0) {
            DateTime now = DateTime.Now;
            string strDate = now.ToShortDateString() + " " + now.ToLongTimeString();
            ListViewItem newItem = new ListViewItem();
            string[] strArry = tmp.Split(':');
            int code = checkUserInfo(strArry[0]);
            if (code == 2) { // 驗證通過
              userHolder.Add(realId, strArry[0]);
              newItem.SubItems.Add(strArry[0]);
              newItem.ImageIndex = 0;
              newItem.SubItems.Add(strDate);
              this.listView2.Items.Add(newItem);
              ind = this.listView2.Items.IndexOf(newItem);
            } else if (code == 1) { /* ... */ }
          }
        } else { // 連線斷開
          this.listView2.Items[ind].ImageIndex = 1;
          keepUser = false; break;
        }
      } catch (Exception e) {
        if (!s.Connected) { this.listView2.Items[ind].ImageIndex = 1; keepUser = false; break; }
      }
    }
  }
  CloseTheThread(realId);
}

private void CloseTheThread(long realId) {
  socketHolder.Remove(realId);
  if (!keepUser) userHolder.Remove(realId);
  lock (this) {
    Thread thd = (Thread)threadHolder[realId];
    threadHolder.Remove(realId);
    thd.Abort();
  }
}

資料載入與廣播機制

public void LoadThread() {
  MethodInvoker mi = new MethodInvoker(this.UpdateListView);
  StreamReader sr = File.OpenText("Issue.txt");
  while ((tmp = sr.ReadLine()) != null) {
    if (tmp == "") break;
    isu.symbol = Mid(tmp, 0, 4);
    isu.bid = Mid(tmp, 4, 5);
    isu.offer = Mid(tmp, 9, 5);
    isu.volume = Mid(tmp, 16, tmp.Length - 16);
    sendMsg = "\v" + tmp + "\n"; // 協議封裝
    SendDataToAllClient(tmp);
    this.BeginInvoke(mi);
    JobDone.WaitOne();
  }
  sr.Close(); fThd.Abort();
}

private void SendDataToAllClient(string str) {
  foreach (Socket s in socketHolder.Values) {
    if (s.Connected) {
      Byte[] byteData = ASCII.GetBytes(str.ToCharArray());
      s.Send(byteData, byteData.Length, 0);
    }
  }
}

架構特色:伺服器/客戶端均採「背景執行緒讀取資料 → BeginInvoke 委派主執行緒更新 UI」模式,確保 WinForms 單執行緒 UI 模型安全。

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