C#基于Socket实现简单聊天室功能

Tallulah ·
更新时间:2024-11-13
· 236 次阅读

因为这段时间在学习Socket,所以就试着写了一个简单的聊天室。主要分为服务器端和多个客户端。利用服务器端作数据中转站,实现消息群发。

1、服务器端有两个类: using System.Collections.Generic; using System.Net; using System.Net.Sockets; namespace 聊天室_Socket_TCP_服务器端 {     class Program     {         static List<Client> clients = new List<Client>();         static List<Client> notClients = new List<Client>();         /// <summary>         /// 广播消息         /// </summary>         /// <param name="message"></param>         public static void CastMessageTOAllConnetedClients(string message)         {             foreach (var client in clients)             {                 if (client.Conneted)                 {                     client.CastMessage(message);                 }                 else                 {                     notClients.Add(client);                 }             }             foreach (var temp in notClients)             {                 clients.Remove(temp);             }         }         static void Main(string[] args)         {                      Socket tcpSever = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);             tcpSever.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.2"), 8899));             tcpSever.Listen(100);//监听是否有客户端发起连接             Console.WriteLine("Begin to listen...");             while (true)             {                 Socket clientSocket = tcpSever.Accept();                 if (clientSocket!=null)                 {                     Console.WriteLine("A client has connneted...");                     Client client = new Client(clientSocket);//将每个新创建的连接通信放于client类做通信                     clients.Add(client);                 }             }             Console.ReadKey();         }     } } using System; using System.Net.Sockets; using System.Text; using System.Threading; namespace 聊天室_Socket_TCP_服务器端 {     /// <summary>     /// 利用该类和客户端做通信     /// </summary>     class Client     {         public Socket clientSocket;         private Thread mesManageTherad;          private byte[] bufffer=new byte[20];         public Client(Socket soc)         {             clientSocket = soc;             //由于消息是不断发送的,需要多次进行处理。这里开一个线程,专门用来处理消息。             mesManageTherad = new Thread(MessageSendFromClient);             mesManageTherad.Start();         }         private void MessageSendFromClient()         {             //开启的线程一直检测客户端客户端发过来的消息             while (true)             {                 //判断连接是否断开,  SelectMode.SelectRead读状态模式。                 //poll已断开返回true                 if (clientSocket.Poll(10,SelectMode.SelectRead)==true)                     {                     clientSocket.Close();                     break;//终止本线程                 }                     int byteNum = clientSocket.Receive(bufffer);//从客户端接受消息                     string mes = Encoding.UTF8.GetString(bufffer, 0 , byteNum);                     Console.WriteLine("客户端发送过来的消息:"+mes);                     //广播消息出去给每个客户端                     Program.CastMessageTOAllConnetedClients(mes);//对CastMessage的一层封装             }         }         /// <summary>         /// Send messages to Clients         /// </summary>         public void CastMessage(string message)         {             byte[] data = Encoding.UTF8.GetBytes(message);             clientSocket.Send(data);         }         /// <summary>         /// 判断是否断开连接         /// </summary>         public bool Conneted         {             get             {                 return clientSocket.Connected;             }         }     } }

服务器端逻辑:

这里的服务器主要负责建立连接,接受客户端消息,广播客户端发来的消息。
服务器通过socket对象绑定服务器IP和相应端口号(端口号自己开,没有被其他软件占用就好),通过Listen监听和服务器socket对象的Accept方法捕捉连接到服务器的客户端socket,将捕捉到的客户端socket放入List集合中方便统一管理和后面的消息群发。
关于捕捉到的客户端socket的逻辑处理放在了Client类中统一管理。
Client类将收到客户端的消息进行接受,在Client中开启一个线程用于不断得检测是否有新消息从客户端发送过来,若有消息发送过来则通过CastMessageTOAllConnetedClients方法(对socket对象的Send方法的封装)发送给每一个客户端。

2.客户端

客户端是在Unity中使用NGUI插件简单开发的一个聊天界面。把脚本挂在NGUI控件上即可。客户端主要负责显示消息,发送消息,接收消息。

using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using UnityEngine; public class ChatManager : MonoBehaviour {     private string _ipAdress = "192.168.1.2";     private int _port=8899;     EndPoint remotPoint;     Socket clientSocket;     public UIInput buttonInput;     private bool isCanSend=false;     private string buttonMessage=null;     Thread receiveThread;     byte[] bufferReceive = new byte[1024];     public UILabel chatWindowLable;     private string message = "";//默认为空串     // Use this for initialization     void Start () {         ConnetToSever(_ipAdress, _port);//与服务器建立连接     }     // Update is called once per frame     void Update () {         if (message!=null&&message!="")         {             chatWindowLable.text += "\n" + message;             message = "";//清空消息         }     }     void ConnetToSever(string ipadress,int port)     {         clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);         remotPoint = new IPEndPoint(IPAddress.Parse(ipadress),port);         //建立连接         clientSocket.Connect(remotPoint);         //因为是一直在准备接受的状态,所以开启一个线程来负责处理接受消息         receiveThread = new Thread(ReceiveMessageFormSever);         receiveThread.Start();     }     private new void SendMessage(string message)     {         byte [] buffer= Encoding.UTF8.GetBytes(message);         clientSocket.SendTo(buffer,remotPoint);     }     public void OnSendButtonClickS()     {         if (buttonInput.value!=null)         {             buttonMessage = buttonInput.value;         }         else         {             buttonMessage = "输入框为空!";         }         SendMessage(buttonMessage);         buttonInput.value = "";     }     private void ReceiveMessageFormSever()     {         while (true)         {             if (clientSocket.Connected)             {                 int length = clientSocket.Receive(bufferReceive);                 message = Encoding.UTF8.GetString(bufferReceive, 0, length);                 //ps:不要在单独的线程里面操作unity组件             }             else             {                 break;             }         }     } }

在客户端中同样有一个socket对象,这个对象通过ConnetToSever方法连接到服务器。在这里,假如某个客户端通过输入框输入文本被客户端脚本捕捉,它将以流的方式发送到服务器,服务器接受到文本,并在服务器端将文本群发至每个客户端。服务器开设了一个线程专门用于捕捉客户端发来的消息,当然,客户端也有相应的线程时刻捕捉服务器发来的消息。消息被客户端捕捉到了,就可以显示在各自的客户端界面上了。



C# 聊天室 socket

需要 登录 后方可回复, 如果你还没有账号请 注册新账号