C# implements Socket message sending and receiving, ServerSocket, ClientSocket

        I know the principle of Socket, but I have never tried how to operate it in the code. I have implemented a preliminary demo of Socket server and client connection, but I have not implemented more advanced serial transmission, encryption and decryption processing, queue and interrupt. If you are interested, you can try again by yourself if you are interested in reconnecting the line.
It is mainly divided into server Socket and client Socket. It only uses a simple string to byte[] transfer test to send and receive messages.
On the server side, a preliminary SocketID management is implemented.
ServerSocket and ClientSocket are divided into ServerSocket and ClientSocket to specifically implement the sending and receiving logic between the server and the client.

For the implementation of ServerSocket, start a separate project.

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; }
        }
    }
}

Implementation of 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));
            }
        }
    }
}

test:

Start ServerSocket first, then start two ClientSockets.

The client sends all to the server to broadcast to all clients, and sends single to the server to return messages only point-to-point.

The test results are as follows:

 

Guess you like

Origin blog.csdn.net/u013476751/article/details/128551650