最近在園子里看了大神寫的( "面試官,不要再問我三次握手和四次揮手" ),忍不住寫段程式來測試一番。 在網上找了很多例子,大多只實現了TCP點對點通訊,但實際應用中,一個伺服器埠往往要監聽多個客戶端發來 ...
最近在園子里看了大神寫的(面試官,不要再問我三次握手和四次揮手),忍不住寫段程式來測試一番。
在網上找了很多例子,大多只實現了TCP點對點通訊,但實際應用中,一個伺服器埠往往要監聽多個客戶端發來的消息。
測試工具下載:https://download.csdn.net/download/nbyanghuichao/11872360
本例採用System.Threading實現多線程監聽,下麵只介紹核心代碼,省略了消息提示和錯誤處理,可以從我的GitHub獲取完整代碼:https://github.com/FB208/CodeSpace/tree/master/CodeSpace.CSharp/TCP.Client
數據聲明:
private string _ip;//IP
private int _port;//埠
//客戶端集合
public static List<TcpClientModel> clients = new List<TcpClientModel>
private static byte[] bytes = new byte[1024 * 100];
/// <summary>
/// 用於存儲客戶端
/// </summary>
public class TcpClientModel
{
/// <summary>
/// IP:Port
/// </summary>
public string RemoteEndPoint { get; set; }
/// <summary>
/// 客戶端鏈接對象
/// </summary>
public TcpClient TcpClient { get; set; }
}
啟動監聽:
///啟動監聽
void Init()
{
try
{
IPAddress ip = IPAddress.Parse(_ip);
int port = _port;
TcpListener listener = new TcpListener(ip, port);
//啟動監聽
listener.Start();
tb_console.AppendText($"Listener...\r\n");
//非同步接收 遞歸迴圈接收多個客戶端
listener.BeginAcceptTcpClient(new AsyncCallback(GetAcceptTcpclient), listener);
}
catch (Exception ex)
{
}
}
接收客戶端:
private void GetAcceptTcpclient(IAsyncResult State)
{
//處理多個客戶端接入
TcpListener listener = (TcpListener)State.AsyncState;
//接收到客戶端請求
TcpClient client = listener.EndAcceptTcpClient(State);
//保存到客戶端集合中
clients.Add(new TcpClientModel() { TcpClient = client, RemoteEndPoint = client.Client.RemoteEndPoint.ToString() });
//開啟線程用來持續接收來自客戶端的數據
Thread myThread = new Thread(() =>
{
ReceiveMsgFromClient(client);
});
myThread.Start();
listener.BeginAcceptTcpClient(new AsyncCallback(GetAcceptTcpclient), listener);
}
接收消息並響應客戶端:
private void ReceiveMsgFromClient(object reciveClient)
{
TcpClient client = reciveClient as TcpClient;
if (client == null)
{
return;
}
while (true)
{
try
{
NetworkStream stream = client.GetStream();
int num = stream.Read(bytes, 0, bytes.Length); //將數據讀到result中,並返回字元長度
if (num != 0)
{
//把位元組數組中流存儲的數據以字元串方式賦值給str
//這裡就是接收到的客戶端消息
string str = Encoding.UTF8.GetString(bytes, 0, num);
//給客戶端返回一個消息
string msg = "Your message has been received by the server[" + str + "]";
bool result = TCPHelper.SendToClient(client, msg, out msg);
if (!result)
{
//發送失敗
}
}
else
{
//這裡需要註意 當num=0時表明客戶端已經斷開連接,需要結束迴圈,不然會死迴圈一直卡住
break;
}
}
catch (Exception ex)
{
//鏈接失敗 從集合中移除出錯客戶端
clients.Remove(clients.FirstOrDefault(m => m.RemoteEndPoint == client.Client.RemoteEndPoint.ToString()));
break;
}
}
}
從伺服器向客戶端發送消息的工具類:
public static class TCPHelper
{
public static bool SendToClient(TcpClient client, string message,out string errorMsg)
{
try
{
byte[] bytes = new byte[1024 * 100];
bytes = Encoding.UTF8.GetBytes(message);
NetworkStream stream = client.GetStream();
stream.Write(bytes, 0, bytes.Length);
stream.Flush();
errorMsg = "";
return true;
}
catch (Exception ex)
{
errorMsg = ex.Message;
return false;
}
}
}
測試效果:
完整代碼請關註:https://github.com/FB208/CodeSpace/tree/master/CodeSpace.CSharp/TCP.Client