Demo - 基于.NET+Socket实现多人聊天室

(一)Demo涉及技术

开发语言:C#
GUI:WPF(MVVM)
框架:Prism(不重要)
核心包:System.Net.Sockets

(二)功能演示

e2274f1a-7164-45ff-a532-3304fb36e9d8.gif
Demo采用C#\WPF\MVVM,包含一个服务端应用、一个客户端应用。

(三)核心代码

服务端代码

  private void StartServer()
  {
      if (ServerSocket != null) return;

      // 1 创建服务端Socket
      ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

      // 2 Bind
      IPAddress iPAddress = IPAddress.Parse(ServerIp);
      IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, ServerPort);
      ServerSocket.Bind(iPEndPoint);

      // 3 Listen
      ServerSocket.Listen(MaxConnect);


      State = "已启动";
      RemindMessage(ServerSocket.LocalEndPoint?.ToString() ?? "", EndPointType.Local, "服务已启动!");

      // 4 Accept
      Task.Run(() => Accept(ServerSocket));
  }

    /// <summary>
    /// 等待客户端连接服务端
    /// </summary>
    /// <param name="serverSocket"></param>
    private void Accept(Socket serverSocket)
    {
        while (true)
        {
          	// Accept方法会造成此线程的阻塞,等待客户端的连接
            Socket clientSocket = serverSocket.Accept();
            RemindClinetOnline(clientSocket);

            // Receive
            Task.Run(() => Receive(clientSocket));
        }
    }

    /// <summary>
    /// 接收客户端发送消息
    /// </summary>
    /// <param name="clinetSocket"></param>
    private void Receive(Socket clinetSocket)
    {
        byte[] data = new byte[1024 * 1024];

        while (clinetSocket.Connected)
        {
            //读取客户端发送过来的数据
            int readLeng = clinetSocket.Receive(data, 0, data.Length, SocketFlags.None);
            //客户端断开连接
            if (readLeng == 0)
            {
                RemindClinetOffline(clinetSocket);
                break;
            }
	
            string content = Encoding.UTF8.GetString(data, 0, readLeng);
            RemindMessage(clinetSocket.RemoteEndPoint?.ToString() ?? "", EndPointType.Remote, content);

            // 转发到各个连接的客户端
            var contentByte = Encoding.UTF8.GetBytes(content);
            foreach (var clientSocket in ConnectedSockets.Except(new List<Socket>() { clinetSocket }))
            {
                clientSocket.Send(contentByte);
            }
        }
    }

客户端代码

  private void ConnectServer()
  {
      if (ClientSocket != null) return;

      // 1 创建服务端Socket
      ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

      // 2 Connect
      IPAddress iPAddress = IPAddress.Parse(ServerIp);
      IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, ServerPort);
      ClientSocket.Connect(iPEndPoint);

      //RemindClinetOnline(ClientSocket);
      Application.Current.Dispatcher.Invoke(() => { State = "已连接"; });
      RemindMessage(clientSocket?.LocalEndPoint?.ToString() ?? "", EndPointType.Local, "启动连接");


      // 4 Accept
      Task.Run(() => Receive(ClientSocket));
  }

  private void DisconnectServer()
  {
      if (ClientSocket == null) return;

      RemindMessage(ClientSocket.LocalEndPoint?.ToString() ?? "", EndPointType.Local, "断开连接");
      Application.Current.Dispatcher.Invoke(() => { State = "未连接"; });


      // 停止会话
      ClientSocket.Shutdown(SocketShutdown.Both);
      // 关闭连接
      ClientSocket.Close();
      ClientSocket = null;
  }

  private void SendMessage()
  {
      if (ClientSocket == null || string.IsNullOrEmpty(InputMessage)) return;

      // 发送到连接到客户端
      var sendBytes = Encoding.UTF8.GetBytes(InputMessage);
      ClientSocket.Send(sendBytes);

      RemindMessage(ClientSocket?.LocalEndPoint?.ToString() ?? "", EndPointType.Local, InputMessage);
      Application.Current.Dispatcher.Invoke(() => { InputMessage = ""; });
  }


  /// <summary>
  /// 接收客户端发送消息
  /// </summary>
  /// <param name="clientSocket"></param>
  private void Receive(Socket clientSocket)
  {
      byte[] data = new byte[1024 * 1024];
      while (true)
      {
          //读取客户端发送过来的数据
          int readLeng = ClientSocket.Receive(data, 0, data.Length, SocketFlags.None);

          //客户端断开连接,在客户端关闭命令发出后,会再接收到一次服务端发来的信息
          if (readLeng == 0) break;

          string content = Encoding.UTF8.GetString(data, 0, readLeng);
          RemindMessage(clientSocket?.RemoteEndPoint?.ToString() ?? "", EndPointType.Remote, content);
      }
  }

(四).NET/Socket中服务端和服务端的工作过程

(五)项目地址

GitHub - FXChat

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值