C#制作简单的多人在线即时交流聊天室

这里是 C# 制作简单的多人在线即时交流聊天室的攻略。下面我们将分步骤介绍实现过程。

准备工作

  • 编程环境:Visual Studio 2017 或更高版本。
  • 知识储备:C# .NET 基础知识、Socket 编程、多线程编程、WinForm 界面开发等。

实现步骤

1. 创建 WinForm 应用程序

打开 Visual Studio,创建一个新的 WinForm 应用程序项目。该项目的名字为 ChatRoom。

2. 设计聊天界面

在设计窗口中添加四个控件,以实现多人即时聊天室:

  • 一个 ListBox 控件,用于显示聊天记录。
  • 一个 TextBox 控件,用于输入发送的内容。
  • 一个 Button 控件,用于发送消息。
  • 一个 Label 控件,用于显示在线用户的数量。

3. 实现服务器端

服务器端将使用 C# Socket 编程实现。在解决方案资源管理器中创建一个名为 Server 的新控制台应用程序项目,并添加以下代码:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Server {
    class Program {
        static Hashtable clientsList = new Hashtable();

        static void Main(string[] args) {
            TcpListener serverSocket = new TcpListener(IPAddress.Any, 8080);
            TcpClient clientSocket = default(TcpClient);
            int counter = 0;

            serverSocket.Start();
            Console.WriteLine("Server started...");

            while (true) {
                counter += 1;
                clientSocket = serverSocket.AcceptTcpClient();

                byte[] bytesFrom = new byte[clientSocket.ReceiveBufferSize];
                string dataFromClient = null;

                NetworkStream networkStream = clientSocket.GetStream();
                networkStream.Read(bytesFrom, 0, clientSocket.ReceiveBufferSize);
                dataFromClient = Encoding.Unicode.GetString(bytesFrom);
                dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));

                clientsList.Add(dataFromClient, clientSocket);

                Broadcast(dataFromClient + " joined ", dataFromClient, false);

                Console.WriteLine(dataFromClient + " joined chat room ");
                handleClient client = new handleClient();
                client.startClient(clientSocket, dataFromClient, clientsList);
            }

            clientSocket.Close();
            serverSocket.Stop();

            Console.WriteLine("exit");
            Console.ReadLine();
        }

        public static void Broadcast(string msg, string uName, bool flag) {
            foreach (DictionaryEntry Item in clientsList) {
                TcpClient broadcastSocket;
                broadcastSocket = (TcpClient)Item.Value;
                NetworkStream broadcastStream = broadcastSocket.GetStream();
                Byte[] broadcastBytes = null;

                if (flag) {
                    broadcastBytes = Encoding.Unicode.GetBytes(uName + " says : " + msg);
                } else {
                    broadcastBytes = Encoding.Unicode.GetBytes(msg);
                }

                broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                broadcastStream.Flush();
            }
        }
    }

    public class handleClient {
        TcpClient clientSocket;
        string clNo;
        Hashtable clientsList;

        public void startClient(TcpClient inClientSocket, string clineNo, Hashtable cList) {
            this.clientSocket = inClientSocket;
            this.clNo = clineNo;
            this.clientsList = cList;
            Thread ctThread = new Thread(doChat);
            ctThread.Start();
        }

        private void doChat() {
            byte[] bytesFrom = new byte[clientSocket.ReceiveBufferSize];
            string dataFromClient = null;

            while (true) {
                try {
                    NetworkStream networkStream = clientSocket.GetStream();
                    networkStream.Read(bytesFrom, 0, clientSocket.ReceiveBufferSize);
                    dataFromClient = Encoding.Unicode.GetString(bytesFrom);
                    dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));

                    Program.Broadcast(dataFromClient, clNo, true);
                } catch {
                    Console.WriteLine(clNo + " disconnected");
                    clientsList.Remove(clNo);
                    Broadcast(clNo + " disconnected", "", false);
                    break;
                }
            }
        }

        public void Broadcast(string msg, string uName, bool flag) {
            byte[] broadcastBytes = null;

            if (flag) {
                broadcastBytes = Encoding.Unicode.GetBytes(uName + " says : " + msg);
            } else {
                broadcastBytes = Encoding.Unicode.GetBytes(msg);
            }

            NetworkStream broadcastStream = clientSocket.GetStream();
            broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
            broadcastStream.Flush();
        }
    }
}

4. 实现客户端

客户端也使用 C# Socket 编程实现。在 ChatRoom 项目中添加一个新的类,名为 ChatClient,并添加以下代码:

using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace ChatRoom {
    public partial class ChatClient : Form {
        private TcpClient clientSocket = new TcpClient();
        private NetworkStream serverStream = default(NetworkStream);
        private string readData = null;

        public ChatClient() {
            InitializeComponent();
        }

        private void btnConnect_Click(object sender, EventArgs e) {
            readData = "Connecting to chat room server...";
            msg();
            clientSocket.Connect("127.0.0.1", 8080);
            serverStream = clientSocket.GetStream();

            byte[] outStream = Encoding.Unicode.GetBytes(txtUser.Text + "$");
            serverStream.Write(outStream, 0, outStream.Length);
            serverStream.Flush();

            Thread ctThread = new Thread(getMessage);
            ctThread.Start();
        }

        private void btnSend_Click(object sender, EventArgs e) {
            byte[] outStream = Encoding.Unicode.GetBytes(txtMsg.Text + "$");
            serverStream.Write(outStream, 0, outStream.Length);
            serverStream.Flush();
            txtMsg.Text = "";
        }

        private void getMessage() {
            while (true) {
                serverStream = clientSocket.GetStream();
                int buffSize = 0;
                byte[] inStream = new byte[clientSocket.ReceiveBufferSize];
                buffSize = clientSocket.ReceiveBufferSize;
                serverStream.Read(inStream, 0, buffSize);
                string returndata = Encoding.Unicode.GetString(inStream);
                readData = "" + returndata;
                msg();
            }
        }

        private void msg() {
            if (InvokeRequired) {
                this.Invoke(new MethodInvoker(msg));
            } else {
                lstChat.Items.Add(readData);
            }
        }
    }
}

5. 编译并运行聊天室

编译两个项目,启动 ChatRoom 服务器应用程序,并运行 ChatClient 客户端应用程序。在客户端中输入用户名,然后单击“连接”按钮即可加入聊天室。在聊天室中输入消息,然后按下“发送”按钮即可将消息发送给所有在线用户。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#制作简单的多人在线即时交流聊天室 - Python技术站

(0)
上一篇 2023年6月1日
下一篇 2023年6月1日

相关文章

  • 完美解决c# distinct不好用的问题

    以下是关于“完美解决c# distinct不好用的问题”的完整攻略: 问题描述 在 C# 中使用 Distinct() 方法可以去除一个集合中的重复元素,但是如果需要去除自定义类中的成员变量重复的方法时,经常会遇到以下两个问题: 需要先实现 IEqualityComparer 接口; 直接使用 Distinct() 方法对 List 自定义类对象去重会报错。…

    C# 2023年6月1日
    00
  • C#实现多线程的同步方法实例分析

    C#实现多线程的同步方法实例分析 什么是多线程同步? 多线程同步是指多个线程同时访问共享资源时,保证它们的执行顺序符合我们的期望,避免因多线程访问导致资源竞争而导致的程序错误。 常见的多线程同步方法 常见的多线程同步方法包括:锁机制、信号量、互斥体、事件等。 锁机制 锁机制是通过一种约定俗成的方式,确保同一时刻只有一个线程能够访问共享资源。通常我们使用 lo…

    C# 2023年5月15日
    00
  • 如何:对Windows 窗体控件进行线程安全调用

    在Windows窗体应用程序中,多线程操作控件是一种常见的需求。但是,由于控件只能在创建它的线程上访问,因此在多线程环境下操作控件可能会导致线程安全问题。本文将介绍如何对Windows窗体控件进行线程安全调用,以避免这些问题。 使用Control.Invoke方法 Control.Invoke方法是.NET Framework提供的一种线程安全调用控件的方法…

    C# 2023年5月15日
    00
  • WinForm实现按名称递归查找控件的方法

    下面开始讲解WinForm实现按名称递归查找控件的方法的攻略。 什么是WinForm? WinForm是Windows Forms的缩写,是一个在Windows操作系统上创建桌面应用程序的API。WinForm允许开发人员在Windows的桌面环境中创建GUI应用程序,通过WinForm框架,开发人员可以方便地创建一个能够响应用户操作的UI。 控件查找的应用…

    C# 2023年6月6日
    00
  • C# 位运算符整理

    C# 位运算符整理攻略 概述 在C#中,位运算符可以用于对二进制位进行逻辑运算。C#中的常见位运算符有: 按位与(&) 按位或(|) 按位异或(^) 取反(~) 左移(<<) 右移(>>) 按位与(&) 按位与运算符将两个数的二进制位进行比较,如果两个二进制位都为1,则该位的结果为1,否则为0。 示例代码: int a…

    C# 2023年5月31日
    00
  • C#实现多线程写入同一个文件的方法

    实现多线程写入同一文件的方法可以使用C#中的StreamWriter类和Mutex类。StreamWriter类可以实现文本文件的写操作,而Mutex类则可以实现多个线程对同一文件进行互斥访问,从而避免写入冲突。 以下是具体的步骤: 步骤1:创建StreamWriter对象 首先我们需要创建一个StreamWriter对象,指定需要写入的文件路径和编码方式。…

    C# 2023年6月1日
    00
  • C#编程简单实现生成PDF文档的方法示例

    综述 在C#编程中生成PDF文档是一项非常有用的功能。PDF文档可以在任何设备上展示并保留格式,因此它可以被广泛应用于数据报表、电子书等领域。本文将会详细讲述如何使用C#编程实现生成PDF文档的方法,同时提供两个实例来演示如何操作。 步骤 引入PDF库 在C#中生成PDF文档之前,需要下载和使用第三方PDF库。有很多开源的PDF生成库可以方便的使用,例如iT…

    C# 2023年6月1日
    00
  • Unity调用C++ dll实现打开双目相机

    Unity调用C++ dll实现打开双目相机需要以下几个步骤: 编写C++ dll文件 首先,我们需要编写C++ dll文件。C++ dll文件的作用是实现打开双目相机的操作,并将相机返回给Unity。在C++文件中需要定义一个函数来获取左右相机数据,并返回给C#脚本。以下是C++ dll文件的示例: #include<iostream> #in…

    C# 2023年6月7日
    00
合作推广
合作推广
分享本页
返回顶部