標籤:style blog color io os ar 使用 for strong
namespace SyncChatServer{ class User { public TcpClient client{get; private set;} public BinaryReader br{get; private set;} public BinaryWriter bw{get; private set;} public string userName {get; set; } public User(TcpClient client) { this.client = client; NetworkStream networkStream = client.GetStream(); br = new BinaryReader(networkStream); bw = new BinaryWriter(networkStream); } public void Close() { br.Close(); bw.Close(); client.Close(); } }}//聲明了一個客戶的類User
using System;using System.Collections.Generic;using System.Windows.Forms;//添加的命名空間引用using System.Net;using System.Net.Sockets;using System.Threading;namespace SyncChatServer{ public partial class MainForm : Form { /// <summary>儲存串連的所有使用者</summary> private List<User> userList = new List<User>(); /// <summary>使用的本機IP地址</summary> IPAddress localAddress; /// <summary>監聽連接埠</summary> private const int port = 51888; private TcpListener myListener; /// <summary>是否正常退出所有接收線程</summary> bool isNormalExit = false; public MainForm() { InitializeComponent(); listBoxStatus.HorizontalScrollbar = true; IPAddress[] addrIP = Dns.GetHostAddresses(Dns.GetHostName()); localAddress = addrIP[0]; buttonStop.Enabled = false; } /// <summary>【開始監聽】按鈕的Click事件</summary> private void buttonStart_Click(object sender, EventArgs e) { myListener = new TcpListener(localAddress, port); myListener.Start(); //調用string的靜態方法可以指定輸出的格式 AddItemToListBox(string.Format("開始在{0}:{1}監聽客戶串連", localAddress, port)); //建立一個線程監聽用戶端串連請求 Thread myThread = new Thread(ListenClientConnect); myThread.Start(); buttonStart.Enabled = false; buttonStop.Enabled = true; } /// <summary>接收用戶端串連</summary> private void ListenClientConnect() { TcpClient newClient = null; while (true) { try { //在伺服器中,TcpClient對象必須要用AcceptTcpClient();方法擷取 newClient = myListener.AcceptTcpClient(); } catch { //當單擊“停止監聽”或者退出此表單時AcceptTcpClient()會產生異常 //因此可以利用此異常退出迴圈 break; } //每接受一個用戶端串連,就建立一個對應的線程迴圈接收該用戶端發來的資訊 User user = new User(newClient); Thread threadReceive = new Thread(ReceiveData); threadReceive.Start(user); userList.Add(user); AddItemToListBox(string.Format("[{0}]進入", newClient.Client.RemoteEndPoint)); AddItemToListBox(string.Format("當前串連使用者數:{0}", userList.Count)); } } /// <summary> /// 處理接收的用戶端資料 /// </summary> /// <param name="userState">用戶端資訊</param> private void ReceiveData(object userState) { User user = (User)userState; TcpClient client = user.client; while (isNormalExit == false) { string receiveString = null; try { //從網路流中讀出字串,此方法會自動判斷字串長度首碼,並根據長度首碼讀出字串 receiveString = user.br.ReadString(); } catch { if (isNormalExit == false) { AddItemToListBox(string.Format("與[{0}]失去聯絡,已終止接收該使用者資訊", client.Client.RemoteEndPoint)); RemoveUser(user); } break; } AddItemToListBox(string.Format("來自[{0}]:{1}", user.client.Client.RemoteEndPoint, receiveString)); string[] splitString = receiveString.Split(‘,‘); switch (splitString[0]) { case "Login": user.userName = splitString[1]; SendToAllClient(user, receiveString); break; case "Logout": SendToAllClient(user, receiveString); RemoveUser(user); return; case "Talk": string talkString = receiveString.Substring(splitString[0].Length + splitString[1].Length + 2); AddItemToListBox(string.Format("{0}對{1}說:{2}", user.userName, splitString[1], talkString)); SendToClient(user, "talk," + user.userName + "," + talkString); foreach (User target in userList) { if (target.userName == splitString[1] && user.userName != splitString[1]) { SendToClient(target, "talk," + user.userName + "," + talkString); break; } } break; default: AddItemToListBox("什麼意思啊:" + receiveString); break; } } } /// <summary> /// 發送message給user /// </summary> /// <param name="user">指定發給哪個使用者</param> /// <param name="message">資訊內容</param> private void SendToClient(User user, string message) { try { //將字串寫入網路流,此方法會自動附加字串長度首碼 user.bw.Write(message); user.bw.Flush(); AddItemToListBox(string.Format("向[{0}]發送:{1}", user.userName, message)); } catch { AddItemToListBox(string.Format("向[{0}]發送資訊失敗", user.userName)); } } /// <summary>發送資訊給所有客戶</summary> /// <param name="user">指定發給哪個使用者</param> /// <param name="message">資訊內容</param> private void SendToAllClient(User user, string message) { string command = message.Split(‘,‘)[0].ToLower();/////////////////////////////////////////////////////////////// if (command == "login") { for (int i = 0; i < userList.Count; i++) { SendToClient(userList[i], message);//如果是登陸資訊,則發給每個使用者這個資訊 if (userList[i].userName != user.userName)//如果是登陸資訊,則也要發給將要登陸的使用者已經登陸的使用者的名字 { SendToClient(user, "login," + userList[i].userName); } } } else if(command=="logout")//如果是登出,則發送給其餘的每個使用者登出的資訊 { for (int i = 0; i < userList.Count; i++) { if (userList[i].userName != user.userName) { SendToClient(userList[i], message); } } } } /// <summary>移除使用者</summary> /// <param name="user">指定要刪除的使用者</param> private void RemoveUser(User user) { userList.Remove(user); user.Close(); AddItemToListBox(string.Format("當前串連使用者數:{0}", userList.Count)); } private delegate void AddItemToListBoxDelegate(string str); /// <summary>在ListBox中追加狀態資訊</summary> /// <param name="str">要追加的資訊</param> private void AddItemToListBox(string str) { if (listBoxStatus.InvokeRequired) { AddItemToListBoxDelegate d = AddItemToListBox; listBoxStatus.Invoke(d, str); } else { listBoxStatus.Items.Add(str); listBoxStatus.SelectedIndex = listBoxStatus.Items.Count - 1; listBoxStatus.ClearSelected(); } } /// <summary>【停止監聽】按鈕的Click事件</summary> private void buttonStop_Click(object sender, EventArgs e) { AddItemToListBox("開始停止服務,並依次使使用者退出!"); isNormalExit = true; for (int i = userList.Count - 1; i >= 0; i--) { RemoveUser(userList[i]); } //通過停止監聽讓myListener.AcceptTcpClient()產生異常退出監聽線程 myListener.Stop(); buttonStart.Enabled = true; buttonStop.Enabled = false; } /// <summary>關閉視窗時觸發的事件</summary> private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { if (myListener != null) { //引發buttonStop的Click事件 buttonStop.PerformClick(); } } }}
Tcp小型即時對話訊息程式,基於C#的程式,伺服器端的代碼