C#实现Socket的消息收发,ServerSocket,ClientSocket

该文章提供了一个简单的C#Socket服务器和客户端的实现,包括初始化、连接管理和消息收发。服务器端能广播消息和点对点回应,但未实现序列化、加密、队列及断线重连功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        知道Socket原理,但是一直没有在代码里面尝试怎么操作,闲来无事实现了一个初步的Socket服务器和客户端连接的Demo,但是没有实现更高级一点的系列化传输,加解密处理以及队列和断线重连等处理,感兴趣的话可以自己再尝试尝试。
主要分服务器Socket和客户端Socket,只用了简单的字符串转byte[]的传递测试收发消息。
服务器这边的话实现了个初步的SocketID管理。
分ServerSocket和ClientSocket来具体实现服务器与客户端的收发逻辑。

ServerSocket的实现,单独启个工程。

namespace ServerSocket
{
    class Program
    {
        private static ServerSocketDemo _serverSocket = null;

        static void Main(string[] args)
        {
            _serverSocket = new ServerSocketDemo();
            _serverSocket.Initialize(OnReceiveMsgCallback);
        }

        private static void OnReceiveMsgCallback(int socketId, string msg)
        {
            if (!string.IsNullOrEmpty(msg))
            {
                //给所有已连接的客户端发送消息,类似于广播
                if (msg.Contains("all"))
                {
                    _serverSocket.SendMsgToAll("嘿嘿嘿");
                }
                //只给当前发送消息来的客户端回消息,点对点
                if (msg.Contains("single"))
                {
                    _serverSocket.SendMsgByID(socketId, string.Format("你好,{0},收到了你的消息!", socketId));
                }
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace ServerSocket
{
    
    public class ServerSocketDemo
    {
        //IP和端口
        private string IP = "127.0.0.1";
        private int    PORT = 9527;
        private Socket _serverSocket = null;
        //收取数据的缓冲区,每次读取多少数据的缓存
        private byte[] _receiveBuff = new byte[1024];
        //用来处理ClientSocket的ID
        private int _socketID = 0;
        //已连接的客户端Socket
        private Dictionary<int, SocketInfo> _sockets = null;
        //收到客户端消息的回调
        private Action<int, string> _onReceiveMsgCall = null;
        public void Initialize(Action<int, string> receiveMsgCall)
        {
            _onReceiveMsgCall = receiveMsgCall;
            _sockets = new Dictionary<int, SocketInfo>();
            //绑定IP和端口,启动Socket
            _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ipAddress = IPAddress.Parse(IP);
            IPEndPoint ipEndpoint = new IPEndPoint(ipAddress, PORT);
            _serverSocket.Bind(ipEndpoint);
            _serverSocket.Listen(20);
            Console.WriteLine(string.Format("ServerSocket:{0}启动成功!", _serverSocket.LocalEndPoint.ToString()));
            //开个线程接收客户端的消息
            Thread socketTread = new Thread(new ThreadStart(OnClientConnected));
            socketTread.IsBackground = true;
            socketTread.Start();
            Console.ReadKey();
        }

        private void OnClientConnected()
        {
            while (true)
            {
                Socket clientSocket = _serverSocket.Accept();
                Console.WriteLine(string.Format("{0}连接成功!", clientSocket.LocalEndPoint.ToString()));
                Thread receiveThread = new Thread(OnReceiveMsg);
                receiveThread.IsBackground = true;
                //给客户端Socket生成ID并且记录客户端Socket的连接
                SocketInfo socketInfo = new SocketInfo();
                _socketID++;
                socketInfo.ID = _socketID;
                socketInfo.ClientSocket = clientSocket;
                //把连接上的Socket保存起来
                _sockets.Add(socketInfo.ID, socketInfo);
                receiveThread.Start(socketInfo);
            }
        }

        private void OnReceiveMsg(object info)
        {
            SocketInfo socketInfo = info as SocketInfo;
            Socket receiveSocket = socketInfo.ClientSocket;
            while (true)
            {
                try
                {
                    //读取客户端发来的数据,这里没考虑类的系列化,只简单测试字符串的收发
                    int recvLen = receiveSocket.Receive(_receiveBuff);
                    string content = Encoding.UTF8.GetString(_receiveBuff, 0, recvLen);
                    Console.WriteLine(string.Format("收到用户【{0}】发来的消息:{1}", socketInfo.ID, content));
                    //做个回调,处理收到的数据
                    if (_onReceiveMsgCall != null)
                    {
                        _onReceiveMsgCall(socketInfo.ID, content);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("接收消息异常:" + ex.Message);
                    receiveSocket.Shutdown(SocketShutdown.Both);
                    receiveSocket.Close();
                    return;
                }
            }
        }

        /// <summary>
        /// 根据记录的客户端SocketID进行单点的消息发送
        /// </summary>
        /// <param name="socketId"></param>
        /// <param name="msg"></param>
        public void SendMsgByID(int socketId, string msg)
        {
            if (_sockets.ContainsKey(socketId))
            {
                Socket clientSocket = _sockets[socketId].ClientSocket;
                if (clientSocket.Connected)
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(msg);
                    clientSocket.Send(bytes);
                }
            }
        }

        /// <summary>
        /// 发送给所有已连接的客户端
        /// </summary>
        /// <param name="msg"></param>
        public void SendMsgToAll(string msg)
        {
            var iter = _sockets.GetEnumerator();
            while (iter.MoveNext())
            {
                byte[] bytes = Encoding.UTF8.GetBytes(msg);
                iter.Current.Value.ClientSocket.Send(bytes);
            }
        }

        private class SocketInfo
        {
            /// <summary>
            /// 记录Socket的ID
            /// </summary>
            public int ID { get; set; }
            /// <summary>
            /// 客户端的Socket连接
            /// </summary>
            public Socket ClientSocket { get; set; }
        }
    }
}

ClientSocket的实现

using System;

namespace ClientSocket
{
    class Program
    {
        static void Main(string[] args)
        {
            ClientSocketDemo clientSocket = new ClientSocketDemo();
            clientSocket.Initialize();
            clientSocket.SendMsg("你好!");
            while (true)
            {
                //输入数据按回车给服务器发消息
                string newMsg = Console.ReadLine();
                clientSocket.SendMsg(newMsg);
            }
        }
    }
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace ClientSocket
{
    public class ClientSocketDemo
    {
        private string IP = "127.0.0.1";
        private int PORT = 9527;
        private Socket _clientSocket = null;
        private byte[] _buffer = null;
        public void Initialize()
        {
            _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _buffer = new byte[1024];
            IPAddress ip = IPAddress.Parse(IP);
            IPEndPoint endPoint = new IPEndPoint(ip, PORT);
            try
            {
                _clientSocket.Connect(endPoint);
                Console.WriteLine(string.Format("连接{0}服务器成功!", _clientSocket.LocalEndPoint.ToString()));
            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format("连接服务器失败:\n"+ ex.Message));
                return;
            }
            //开线程接收服务器下来的数据
            Thread receiveThread = new Thread(OnReceiveMsg);
            receiveThread.IsBackground = true;
            receiveThread.Start();
        }

        /// <summary>
        /// 接收服务器消息
        /// </summary>
        private void OnReceiveMsg()
        {
            while (true)
            {
                try
                {
                    int receiveLen = _clientSocket.Receive(_buffer);
                    string receiveMsg = Encoding.UTF8.GetString(_buffer, 0, receiveLen);
                    Console.WriteLine(string.Format("收到服务器消息:" + receiveMsg));
                }
                catch (Exception ex)
                {
                    Console.WriteLine("接收消息异常:\n" + ex.Message);
                    _clientSocket.Shutdown(SocketShutdown.Both);
                    _clientSocket.Dispose();
                    Console.ReadKey();
                }
            }
        }

        /// <summary>
        /// 给服务器发消息
        /// </summary>
        public void SendMsg(string msg)
        {
            if (_clientSocket != null && _clientSocket.Connected)
            {
                _clientSocket.Send(Encoding.UTF8.GetBytes(msg));
            }
        }
    }
}

测试:

先启动ServerSocket,然后启动两个ClientSocket.

客户端给服务器发all代表广播给所有客户端,给服务器发single代表只点对点的进行回消息。

测试结果如下:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值