服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C#基于Socket实现简单聊天室功能

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

2022-12-26 14:02Csoap994 C#

这篇文章主要为大家详细介绍了C#基于Socket实现简单聊天室功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

1、服务器端有两个类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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();
        }
    }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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控件上即可。客户端主要负责显示消息,发送消息,接收消息。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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方法连接到服务器。在这里,假如某个客户端通过输入框输入文本被客户端脚本捕捉,它将以流的方式发送到服务器,服务器接受到文本,并在服务器端将文本群发至每个客户端。服务器开设了一个线程专门用于捕捉客户端发来的消息,当然,客户端也有相应的线程时刻捕捉服务器发来的消息。消息被客户端捕捉到了,就可以显示在各自的客户端界面上了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/Csoap2/article/details/98795484

延伸 · 阅读

精彩推荐
  • C#C#微信开发之启用开发者模式

    C#微信开发之启用开发者模式

    本文主要介绍了C#微信开发中启用开发者模式的步骤与方法,具有一定的参考价值,下面跟着小编一起来看下吧...

    likar9212021-12-22
  • C#C#从数据库读取图片并保存的两种方法

    C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...

    风云SH变幻4092022-10-28
  • C#C# 填充Excel图表、图例背景色的实例代码

    C# 填充Excel图表、图例背景色的实例代码

    下面的内容将分别介绍通过C#来设置Excel中图表背景色、以及图表中的图例背景色的方法,需要的朋友可以参考下...

    E-iceblue7502022-07-16
  • C#图形学之Unity渲染管线流程分析

    图形学之Unity渲染管线流程分析

    这篇文章主要介绍了图形学之Unity渲染管线流程的相关资料,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参...

    小紫苏10862022-12-15
  • C#C#子线程执行完后通知主线程的方法

    C#子线程执行完后通知主线程的方法

    下面小编就为大家带来一篇C#子线程执行完后通知主线程的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    C#教程网7842021-12-13
  • C#C#中数组、ArrayList和List三者的区别详解

    C#中数组、ArrayList和List三者的区别详解

    这篇文章主要介绍了C#中数组、ArrayList和List三者的区别详解,对于三者之间的区别想要了解的可以进来了解一下。...

    zhang_xinxiu5742021-12-13
  • C#C# params可变参数的使用注意详析

    C# params可变参数的使用注意详析

    这篇文章主要给大家介绍了关于C# params可变参数的使用注意的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用C#具有一定的参考学习价...

    dudu5462022-07-31
  • C#C# 使用Fiddler捕获本地HttpClient发出的请求操作

    C# 使用Fiddler捕获本地HttpClient发出的请求操作

    这篇文章主要介绍了C# 使用Fiddler捕获本地HttpClient发出的请求操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    丨背水丨4992022-10-12