C#使用Socket實(shí)現(xiàn)本地多人聊天室
本文實(shí)例為大家分享了C#使用Socket實(shí)現(xiàn)本地多人聊天室的具體代碼,供大家參考,具體內(nèi)容如下
【腳本一:Server端】
使用本機(jī)地址:127.0.0.1
完整代碼
using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; ? namespace ConsoleApp1 { ?? ?public class Server ?? ?{ ?? ??? ?Socket mySocket = null; ?? ??? ?Dictionary<IPAddress, Socket> cliDic = new Dictionary<IPAddress, Socket>(); ? ?? ??? ?public void Connect(int port) ?? ??? ?{ ?? ??? ??? ?string IP = "127.0.0.1"; ?? ??? ??? ?//IPAddress IPAddress = IPAddress.Parse("127.0.0.1"); ?? ??? ??? ?IPAddress address = IPAddress.Any; ?? ??? ??? ?//創(chuàng)建IP終結(jié)點(diǎn),把IP地址與端口綁定到網(wǎng)絡(luò)終結(jié)點(diǎn)上 ?? ??? ??? ?IPEndPoint endPoint = new IPEndPoint(address, port); ?? ??? ??? ?//創(chuàng)建客戶端套接字 ?? ??? ??? ?mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ?? ??? ??? ?///監(jiān)聽(tīng)套接字終結(jié)點(diǎn) ?? ??? ??? ?mySocket.Bind(endPoint); ?? ??? ??? ?//服務(wù)端可接收客戶端連接數(shù)量為無(wú)限個(gè) ?? ??? ??? ?mySocket.Listen(0); ?? ??? ??? ?//開(kāi)啟線程監(jiān)聽(tīng)客戶端 ?? ??? ??? ?Thread myThread = new Thread(Listen_Con); ?? ??? ??? ?myThread.Start(); ?? ??? ??? ?Console.WriteLine("開(kāi)始監(jiān)聽(tīng)..."); ?? ??? ?} ? ?? ??? ?/// <summary> ?? ??? ?/// 接收連接的客戶端并存儲(chǔ)客戶端的信息 ?? ??? ?/// </summary> ?? ??? ?/// <param name="obj"></param> ?? ??? ?public void Listen_Con(Object obj) ?? ??? ?{ ?? ??? ??? ?Socket cliSocket = null; ?? ??? ??? ?//持續(xù)監(jiān)聽(tīng)客戶端的請(qǐng)求 ?? ??? ??? ?while (true) ?? ??? ??? ?{ ?? ??? ??? ??? ?try ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?cliSocket = mySocket.Accept(); ?? ??? ??? ??? ?} ?? ??? ??? ??? ?catch (Exception e) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?Console.WriteLine(e.Message); ?? ??? ??? ??? ?} ?? ??? ??? ??? ?string cliEndPoint = cliSocket.RemoteEndPoint.ToString(); ?? ??? ??? ??? ?IPAddress cliAddress = (cliSocket.RemoteEndPoint as IPEndPoint).Address; ?? ??? ??? ??? ?int cliPort = (cliSocket.RemoteEndPoint as IPEndPoint).Port; ?? ??? ??? ??? ?cliDic.Add(cliAddress, cliSocket); ?? ??? ??? ??? ?string MsgStr = "[客戶端結(jié)點(diǎn):" + cliEndPoint + "\n+客戶端IP:" + cliAddress.ToString() + "\n客戶端端口:" + ?? ??? ??? ??? ??? ?cliPort.ToString() + "\n已連接]"; ?? ??? ??? ??? ?byte[] MsgBytes = Encoding.UTF8.GetBytes(MsgStr); ?? ??? ??? ??? ?cliSocket.Send(MsgBytes); ? ?? ??? ??? ??? ?Thread rec_Cli = new Thread(Receive_Con); ?? ??? ??? ??? ?rec_Cli.Start(cliSocket); ?? ??? ??? ??? ?Thread sed_Cli = new Thread(SendToCli); ?? ??? ??? ??? ?sed_Cli.Start(cliSocket); ?? ??? ??? ?} ?? ??? ?} ? ?? ??? ?/// <summary> ?? ??? ?/// 接收已連接的客戶端發(fā)送的消息 ?? ??? ?/// </summary> ?? ??? ?/// <param name="socket"></param> ?? ??? ?public void Receive_Con(Object socket) ?? ??? ?{ ?? ??? ??? ?Socket client = socket as Socket; ?? ??? ??? ?while (true) ?? ??? ??? ?{ ?? ??? ??? ??? ?//創(chuàng)建大小為1024*1024的內(nèi)存緩沖區(qū)(1M) ?? ??? ??? ??? ?byte[] recBytes = new byte[1024 * 1024]; ?? ??? ??? ??? ?//嘗試把接收的字節(jié)存儲(chǔ)到緩沖區(qū) ?? ??? ??? ??? ?try ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?int length = client.Receive(recBytes); ?? ??? ??? ??? ??? ?//把機(jī)器接收的字節(jié)數(shù)組轉(zhuǎn)換為string ?? ??? ??? ??? ??? ?string recMsg = Encoding.UTF8.GetString(recBytes, 0, length); ?? ??? ??? ??? ??? ?//將服務(wù)器接收到的信息轉(zhuǎn)發(fā)到所有已連接的客戶端 ?? ??? ??? ??? ??? ?if (cliDic.Count > 0) ?? ??? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ??? ?foreach (var soc in cliDic) ?? ??? ??? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ??? ??? ?soc.Value.Send(Encoding.UTF8.GetBytes("[" + soc.Value.RemoteEndPoint + "]:" + recMsg)); ?? ??? ??? ??? ??? ??? ?} ?? ??? ??? ??? ??? ?} ?? ??? ??? ??? ??? ?Console.WriteLine("[" + client.RemoteEndPoint + "]:" + recMsg); ?? ??? ??? ??? ?} ?? ??? ??? ??? ?catch (Exception) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?cliDic.Remove((client.RemoteEndPoint as IPEndPoint).Address); ?? ??? ??? ??? ??? ?//客戶端斷開(kāi)的異常 ?? ??? ??? ??? ??? ?Console.WriteLine("[客戶端" + (client.RemoteEndPoint as IPEndPoint).Address + "已斷開(kāi)]"); ?? ??? ??? ??? ??? ?Console.WriteLine("[客戶端終結(jié)點(diǎn):" + client.RemoteEndPoint+"]"); ?? ??? ??? ??? ??? ?//斷開(kāi)套接字 ?? ??? ??? ??? ??? ?client.Close(); ?? ??? ??? ??? ??? ?break; ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ?} ? ?? ??? ?public void SendToCli(object obj) ?? ??? ?{ ?? ??? ??? ?Socket curCliSoc = obj as Socket; ?? ??? ??? ?while (true) ?? ??? ??? ?{ ?? ??? ??? ??? ?byte[] ByteToAll = new byte[1024 * 1024]; ?? ??? ??? ??? ?try ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?string MsgToAll = Console.ReadLine(); ?? ??? ??? ??? ??? ?ByteToAll = Encoding.UTF8.GetBytes("[服務(wù)端]:"+MsgToAll); ?? ??? ??? ??? ??? ?curCliSoc.Send(ByteToAll); ?? ??? ??? ??? ?} ?? ??? ??? ??? ?catch(Exception) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?Console.WriteLine("ERROR:" + curCliSoc.RemoteEndPoint + "已與服務(wù)端斷開(kāi)!"); ?? ??? ??? ??? ??? ?curCliSoc.Close(); ?? ??? ??? ??? ??? ?if(cliDic.ContainsKey((curCliSoc.RemoteEndPoint as IPEndPoint).Address)) ?? ??? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ??? ?cliDic.Remove((curCliSoc.RemoteEndPoint as IPEndPoint).Address); ?? ??? ??? ??? ??? ?} ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ?} ?? ?} ? ?? ?public class ServerMain ?? ?{ ?? ??? ?static void Main(string[] args) ?? ??? ?{ ?? ??? ??? ?Server s1 = new Server(); ?? ??? ??? ?s1.Connect(8800); ?? ??? ?} ?? ?} }
Server端運(yùn)行結(jié)果:
【腳本二:Client端】
完整代碼
using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; ? namespace ConsoleApp1 { ?? ?public class Client ?? ?{ ?? ??? ?string SerIP = "127.0.0.1"; ?? ??? ?Socket myClient = null; ?? ??? ?Thread ConnectThread = null; ?? ??? ?IPAddress SerAdd; ?? ??? ?IPEndPoint SerEP; ?? ??? ?public void Connect_To_Ser(int port) ?? ??? ?{ ?? ??? ??? ?myClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ?? ??? ??? ?SerAdd = IPAddress.Parse(SerIP); ?? ??? ??? ?SerEP = new IPEndPoint(SerAdd, port); ?? ??? ??? ?while (true) ?? ??? ??? ?{ ?? ??? ??? ??? ?try ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?myClient.Connect(SerEP); ?? ??? ??? ??? ??? ?break; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?catch ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?Console.WriteLine("無(wú)法連接到服務(wù)端,請(qǐng)重試..."); ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ??? ?ConnectThread = new Thread(Receive_Ser); ?? ??? ??? ?ConnectThread.Start(); ?? ??? ?} ? ?? ??? ?public void Receive_Ser() ?? ??? ?{ ?? ??? ??? ?while (true) ?? ??? ??? ?{ ?? ??? ??? ??? ?byte[] SerBytes = new byte[1024 * 1024]; ?? ??? ??? ??? ?try ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?int length = myClient.Receive(SerBytes); ?? ??? ??? ??? ??? ?string Msg = Encoding.UTF8.GetString(SerBytes, 0, length); ?? ??? ??? ??? ??? ?Console.WriteLine(Msg); ?? ??? ??? ??? ?} ?? ??? ??? ??? ?catch (Exception) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?Console.WriteLine("已與服務(wù)端斷開(kāi)連接..."); ?? ??? ??? ??? ??? ?break; ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ?} ? ?? ??? ?public void SendToSer() ?? ??? ?{ ?? ??? ??? ?while (true) ?? ??? ??? ?{ ?? ??? ??? ??? ?try ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?string SendMsg = Console.ReadLine(); ?? ??? ??? ??? ??? ?myClient.Send(Encoding.UTF8.GetBytes(SendMsg)); ?? ??? ??? ??? ?} ?? ??? ??? ??? ?catch (Exception) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?Console.WriteLine("[SendToSer]已斷開(kāi)連接"); ?? ??? ??? ??? ??? ?break; ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ?} ?? ?} ? ?? ?public class ClienMain ?? ?{ ?? ??? ?static void Main(string[] Args) ?? ??? ?{ ?? ??? ??? ?Client c1 = new Client(); ?? ??? ??? ?c1.Connect_To_Ser(8800); ?? ??? ??? ?c1.SendToSer(); ?? ??? ?} ?? ?} }
客戶端運(yùn)行效果:
①客戶端先于服務(wù)端運(yùn)行
②客戶端遲于服務(wù)端運(yùn)行
暫時(shí)總效果:
功能完善:
①客戶端連上服務(wù)端后若服務(wù)端斷開(kāi)再打開(kāi),客戶端無(wú)法重連
②心跳包重連
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#中使用基數(shù)排序算法對(duì)字符串進(jìn)行排序的示例
Radix Sort基數(shù)排序是非比較型的排序算法,其時(shí)間復(fù)雜度是O(k·n),n為元素個(gè)數(shù),為數(shù)字位數(shù),這里我們就來(lái)看一下C#中使用基數(shù)排序算法堆字符串進(jìn)行排序的示例2016-06-06C# 動(dòng)態(tài)調(diào)用WebService的示例
這篇文章主要介紹了C# 動(dòng)態(tài)調(diào)用WebService的示例,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2020-11-11c# 重載WndProc,實(shí)現(xiàn)重寫(xiě)“最小化”的實(shí)現(xiàn)方法
在做“亦歌桌面版”的時(shí)候,發(fā)現(xiàn)當(dāng)打開(kāi)歌詞狀態(tài)下,用最小化隱藏窗體到托盤(pán)的話(如下code #1),在調(diào)出發(fā)現(xiàn)歌詞縮小了(雖然顯現(xiàn)的窗體大小跟剛才一樣),從這點(diǎn)看調(diào)用該方法其實(shí)窗體大小是改變了的(這個(gè)過(guò)程只是不可視而已)。2009-02-02c#實(shí)現(xiàn)適配器模式的項(xiàng)目實(shí)踐
適配器模式將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另一個(gè)接口,使得原本由于接口不兼容而不能一起工作的那些類可以一起工作,本文主要介紹了c#實(shí)現(xiàn)適配器模式的項(xiàng)目實(shí)踐,感興趣的可以一起來(lái)了解一下2023-08-08Unity游戲開(kāi)發(fā)實(shí)現(xiàn)背包系統(tǒng)的示例詳解
這篇文章主要為大家介紹了Unity游戲開(kāi)發(fā)實(shí)現(xiàn)背包系統(tǒng)的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08