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

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

服务器之家 - 编程语言 - C# - C#使用Socket实现本地多人聊天室

C#使用Socket实现本地多人聊天室

2022-12-25 15:36.roughbonbon C#

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

本文实例为大家分享了C#使用Socket实现本地多人聊天室的具体代码,供大家参考,具体内容如下

【脚本一:Server端】

使用本机地址:127.0.0.1

完整代码

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
 
namespace ConsoleApp1
{
    public class Server
    {
        Socket mySocket = null;
        Dictionary<IPAddress, Socket> cliDic = new Dictionary<IPAddress, Socket>();
 
        public void Connect(int port)
        {
            string IP = "127.0.0.1";
            //IPAddress IPAddress = IPAddress.Parse("127.0.0.1");
            IPAddress address = IPAddress.Any;
            //创建IP终结点,把IP地址与端口绑定到网络终结点上
            IPEndPoint endPoint = new IPEndPoint(address, port);
            //创建客户端套接字
            mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            ///监听套接字终结点
            mySocket.Bind(endPoint);
            //服务端可接收客户端连接数量为无限个
            mySocket.Listen(0);
            //开启线程监听客户端
            Thread myThread = new Thread(Listen_Con);
            myThread.Start();
            Console.WriteLine("开始监听...");
        }
 
        /// <summary>
        /// 接收连接的客户端并存储客户端的信息
        /// </summary>
        /// <param name="obj"></param>
        public void Listen_Con(Object obj)
        {
            Socket cliSocket = null;
            //持续监听客户端的请求
            while (true)
            {
                try
                {
                    cliSocket = mySocket.Accept();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
                string cliEndPoint = cliSocket.RemoteEndPoint.ToString();
                IPAddress cliAddress = (cliSocket.RemoteEndPoint as IPEndPoint).Address;
                int cliPort = (cliSocket.RemoteEndPoint as IPEndPoint).Port;
                cliDic.Add(cliAddress, cliSocket);
                string MsgStr = "[客户端结点:" + cliEndPoint + "\n+客户端IP:" + cliAddress.ToString() + "\n客户端端口:" +
                    cliPort.ToString() + "\n已连接]";
                byte[] MsgBytes = Encoding.UTF8.GetBytes(MsgStr);
                cliSocket.Send(MsgBytes);
 
                Thread rec_Cli = new Thread(Receive_Con);
                rec_Cli.Start(cliSocket);
                Thread sed_Cli = new Thread(SendToCli);
                sed_Cli.Start(cliSocket);
            }
        }
 
        /// <summary>
        /// 接收已连接的客户端发送的消息
        /// </summary>
        /// <param name="socket"></param>
        public void Receive_Con(Object socket)
        {
            Socket client = socket as Socket;
            while (true)
            {
                //创建大小为1024*1024的内存缓冲区(1M)
                byte[] recBytes = new byte[1024 * 1024];
                //尝试把接收的字节存储到缓冲区
                try
                {
                    int length = client.Receive(recBytes);
                    //把机器接收的字节数组转换为string
                    string recMsg = Encoding.UTF8.GetString(recBytes, 0, length);
                    //将服务器接收到的信息转发到所有已连接的客户端
                    if (cliDic.Count > 0)
                    {
                        foreach (var soc in cliDic)
                        {
                            soc.Value.Send(Encoding.UTF8.GetBytes("[" + soc.Value.RemoteEndPoint + "]:" + recMsg));
                        }
                    }
                    Console.WriteLine("[" + client.RemoteEndPoint + "]:" + recMsg);
                }
                catch (Exception)
                {
                    cliDic.Remove((client.RemoteEndPoint as IPEndPoint).Address);
                    //客户端断开的异常
                    Console.WriteLine("[客户端" + (client.RemoteEndPoint as IPEndPoint).Address + "已断开]");
                    Console.WriteLine("[客户端终结点:" + client.RemoteEndPoint+"]");
                    //断开套接字
                    client.Close();
                    break;
                }
            }
        }
 
        public void SendToCli(object obj)
        {
            Socket curCliSoc = obj as Socket;
            while (true)
            {
                byte[] ByteToAll = new byte[1024 * 1024];
                try
                {
                    string MsgToAll = Console.ReadLine();
                    ByteToAll = Encoding.UTF8.GetBytes("[服务端]:"+MsgToAll);
                    curCliSoc.Send(ByteToAll);
                }
                catch(Exception)
                {
                    Console.WriteLine("ERROR:" + curCliSoc.RemoteEndPoint + "已与服务端断开!");
                    curCliSoc.Close();
                    if(cliDic.ContainsKey((curCliSoc.RemoteEndPoint as IPEndPoint).Address))
                    {
                        cliDic.Remove((curCliSoc.RemoteEndPoint as IPEndPoint).Address);
                    }
                }
            }
        }
    }
 
    public class ServerMain
    {
        static void Main(string[] args)
        {
            Server s1 = new Server();
            s1.Connect(8800);
        }
    }
}

Server端运行结果:

C#使用Socket实现本地多人聊天室

【脚本二:Client端】

完整代码

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
 
namespace ConsoleApp1
{
    public class Client
    {
        string SerIP = "127.0.0.1";
        Socket myClient = null;
        Thread ConnectThread = null;
        IPAddress SerAdd;
        IPEndPoint SerEP;
        public void Connect_To_Ser(int port)
        {
            myClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            SerAdd = IPAddress.Parse(SerIP);
            SerEP = new IPEndPoint(SerAdd, port);
            while (true)
            {
                try
                {
                    myClient.Connect(SerEP);
                    break;
                }
                catch
                {
                    Console.WriteLine("无法连接到服务端,请重试...");
                }
            }
            ConnectThread = new Thread(Receive_Ser);
            ConnectThread.Start();
        }
 
        public void Receive_Ser()
        {
            while (true)
            {
                byte[] SerBytes = new byte[1024 * 1024];
                try
                {
                    int length = myClient.Receive(SerBytes);
                    string Msg = Encoding.UTF8.GetString(SerBytes, 0, length);
                    Console.WriteLine(Msg);
                }
                catch (Exception)
                {
                    Console.WriteLine("已与服务端断开连接...");
                    break;
                }
            }
        }
 
        public void SendToSer()
        {
            while (true)
            {
                try
                {
                    string SendMsg = Console.ReadLine();
                    myClient.Send(Encoding.UTF8.GetBytes(SendMsg));
                }
                catch (Exception)
                {
                    Console.WriteLine("[SendToSer]已断开连接");
                    break;
                }
            }
        }
    }
 
    public class ClienMain
    {
        static void Main(string[] Args)
        {
            Client c1 = new Client();
            c1.Connect_To_Ser(8800);
            c1.SendToSer();
        }
    }
}

客户端运行效果:

①客户端先于服务端运行

C#使用Socket实现本地多人聊天室

②客户端迟于服务端运行

C#使用Socket实现本地多人聊天室

暂时总效果:

C#使用Socket实现本地多人聊天室

功能完善:

①客户端连上服务端后若服务端断开再打开,客户端无法重连

②心跳包重连

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

原文链接:https://blog.csdn.net/weixin_37704259/article/details/104780401

延伸 · 阅读

精彩推荐
  • C#C#集合遍历时删除和增加元素的方法

    C#集合遍历时删除和增加元素的方法

    这篇文章主要介绍了C#集合遍历时删除和增加元素的方法,结合实例形式分析了C#针对集合元素的遍历、添加与删除等操作实现方法与注意事项,需要的朋友可...

    codingsilence8662021-11-29
  • C#C#多线程编程之使用ReaderWriterLock类实现多用户读与单用户写同步的方法

    C#多线程编程之使用ReaderWriterLock类实现多用户读与单用户写同步

    这篇文章主要介绍了C#多线程编程之使用ReaderWriterLock类实现多用户读与单用户写同步的方法,涉及C#多线程操作读写锁定的相关技巧,具有一定参考借鉴价值...

    mile9992021-11-03
  • C#C#实现PDF签名时添加时间戳的2种方法(附VB.NET代码)

    C#实现PDF签名时添加时间戳的2种方法(附VB.NET代码)

    在PDF添加签名时,支持添加可信时间戳来保证文档的法律效应。本文,将通过C#程序代码介绍如何添加可信时间戳,可通过2种方法来实现。感兴趣的可以了...

    E-iceblue11822022-11-20
  • C#C#匿名委托与Lambda表达式详解

    C#匿名委托与Lambda表达式详解

    这篇文章主要为大家详细介绍了C#匿名委托与Lambda表达式的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一...

    DW0395482022-01-20
  • C#C# 线程安全详解

    C# 线程安全详解

    这篇文章主要介绍了c# 线程安全的用法原理及使用示例,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下,希望能够给你带来帮助...

    菜鸟厚非9242022-12-05
  • C#C#中的Lazy如何使用详解

    C#中的Lazy如何使用详解

    这篇文章主要给大家介绍了C#中Lazy如何使用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友...

    码农读书10832022-10-24
  • C#C# winform分页查询的实现示例

    C# winform分页查询的实现示例

    这篇文章主要介绍了C# winform分页查询的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面...

    一枝韩独秀6882022-11-15
  • C#C#实现在listview中插入图片实例代码

    C#实现在listview中插入图片实例代码

    这篇文章主要介绍了C#实现在listview中插入图片实例代码的相关资料,需要的朋友可以参考下...

    net小伙7312021-12-29