在之前的基础上其实我们只需要将客户端发送给服务器的数据在服务器分发给连接的所有客户端即可实现聊天室的功能。
不过在这里我对服务器端的代码重新优化了一下。

客户端连接实例

/// <summary>
    /// 客户端连接实例
    /// </summary>
    class ClientEntity
    {
        public Socket Socket { get; set; }
        public byte[] ReadBuff { get; set; }
    
        /// <summary>
        /// 有效数据长度
        /// </summary>
        public int DataLength { get; set; }
    }

主要代码

public static Socket Socket { get; set; }
        public static List<ClientEntity> ClientEntities { get; set; } // 所有连接的客户端实例
        public static void Main(string[] args)
        {
            Console.WriteLine("Hi,服务器~");
            ClientEntities = new List<ClientEntity>();
    
            #region 绑定ip
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 2233);
    
            Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            Socket.Bind(ipEndPoint);
            Socket.Listen(10);  // 最多支持同时监听 10 个客户端
            Console.WriteLine("[服务器]启动成功!");
            #endregion
    
            // 绑定 Accept
            Socket.BeginAccept(AcceptCallBack, Socket);
    
            Console.ReadLine();
        }

AcceptCallBack

private static void AcceptCallBack(IAsyncResult ar)
        {
            try
            {
                Console.WriteLine("[服务器]有新客户端连接");
                var severSocket = ar.AsyncState as Socket;
                var clientSocket = severSocket.EndAccept(ar);   // 创建客户端连接
                var clientEntity = new ClientEntity { Socket = clientSocket, ReadBuff = new byte[1024] };   // 创建客户端实例
                ClientEntities.Add(clientEntity);
    
                // 开始 Receive
                clientEntity.Socket.BeginReceive(clientEntity.ReadBuff, 0, clientEntity.ReadBuff.Length, SocketFlags.None, ReceiveCallBack, clientEntity);
                // 继续 Accept
                Socket.BeginAccept(AcceptCallBack, Socket);
            }
            catch (SocketException e)
            {
                Console.WriteLine("[服务器Accept-Error]" + e.ErrorCode + "-" + e.Message);
            }
        }

ReceiveCallBack

  private static void ReceiveCallBack(IAsyncResult ar)
        {
            try
            {
                var clientEntity = ar.AsyncState as ClientEntity;   //获取传过来的客户端Socket
                var count = clientEntity.Socket.EndReceive(ar);
                if (count == 0)
                {
                    //关闭客户端连接
                    clientEntity.Socket.Close();
                    ClientEntities.Remove(clientEntity);
                    Console.WriteLine("[服务器]一个客户端已断开连接");

                    return;
                }
                var reciveStr = Encoding.UTF8.GetString(clientEntity.ReadBuff, 0, count); //读取客户端数据
    
                Console.WriteLine("[服务器]收到来自客户端数据:" + reciveStr);


                var sendBytes = Encoding.UTF8.GetBytes("[服务器] 已收到来自客户端的消息:");
                clientEntity.DataLength = count;
                //进行数据分发
                foreach (var item in ClientEntities)
                {
                    item.Socket.BeginSend(sendBytes, 0, count, SocketFlags.None, SendCallBack, clientEntity);
                }
    
                //继续获取数据
                clientEntity.Socket.BeginReceive(clientEntity.ReadBuff, 0, clientEntity.ReadBuff.Length, SocketFlags.None, ReceiveCallBack, clientEntity);
            }
            catch (SocketException e)
            {
    
                Console.WriteLine("[服务器Receive-Error]" + e.ErrorCode + "-" + e.Message);
            }
        }

SendCallBack

 private static void SendCallBack(IAsyncResult ar)
        {
            var clientEntity = ar.AsyncState as ClientEntity;
            Console.WriteLine("[服务器]已向客户端发送数据:" + Encoding.UTF8.GetString(clientEntity.ReadBuff, 0, clientEntity.DataLength));
        }

运行截图:

!{运行截图}(https://i.loli.net/2020/01/16/248FqNKGm7jhgv1.png)

[toc]