因为这段时间在学习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实现简单聊天室功能的详细内容...