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 模型安全。