【C#】一文教你搭个简易的Socket服务器

C#里面提供了Socket类,通过该类,可以很轻松地搭建起Socket服务端和客户端。本文将尽量以最简单的方式、最少的代码量来说明一个简易的Socket服务器是怎么搭建起来的。

首先,大概讲下整个思路和流程:

(1)首先要明白一个概念:整个服务器,实际上就是由一个Socket对象监听端口;

(2)我们会通过一个新的线程监听客户端发起连接请求,这样的好处是避免堵塞主线程;

(3)当与客户端建立起连接之后,我们还会新建线程来专门接受该socket客户端的数据。

先新建各类:

public class SocketServer
{

}

定义一些属性变量:

        //端口号
        private int SocketServerPort = 5002;
        //处理连接请求的线程
        private Thread acceptConnectReqThd;

然后写一个服务器启动的函数Start

       /// 
        /// 启动服务器
        /// 
        public bool Start()
        {
            try
            {
                //创建一个socket对象
                Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //获取IP
                IPAddress ip = IPAddress.Any;
                //创建端口号
                IPEndPoint port = new IPEndPoint(ip, SocketServerPort);
                //监听
                socketWatch.Bind(port);
                Console.WriteLine("监听成功");
                socketWatch.Listen(20);  //设定最大的挂起长度

                //新建线程来处理连接请求
                acceptConnectReqThd = new Thread(AcceptConnectReqHandler);
                acceptConnectReqThd.IsBackground = true;
                acceptConnectReqThd.Start(socketWatch);  //把socket对象当做参数传递给到线程里面的方法

                return true;
            }
            catch(Exception e)
            {
                return false;
            }
        }

执行Start函数之后,我们就创建了一个socket对象,并监听我们设定的端口号5002。并添加了个线程来处理客户端的连接请求。

接下来我们实现AcceptConnectReqHandler方法,即线程驱动的方法:

       /// 
        /// 连接请求的处理函数
        /// 
        /// 
        private void AcceptConnectReqHandler(object _socket)
        {
            try
            {
                //服务端的socket对象
                Socket serverSocket = (Socket)_socket;

                while (true)
                {
                    //获取客户端socket。Accept方法处理任何传入的连接请求,并返回可用于与远程主机通信数据的Socket对象,即客户端的socket。
                    //这一句话会卡主线程。只要没有新的链接进来,就会一直卡主不动(等待中)。
                    //收到连接事件后,会往下执行,通过while又回到这里继续等待
                    Socket clientSocket = serverSocket.Accept();  

                    //创建接受客户端消息的线程
                    Thread acceptMsgReqThd = new Thread(ReciveMsgReqHandler);
                    acceptMsgReqThd.IsBackground = true;
                    acceptMsgReqThd.Start(clientSocket);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("服务端处理连接事件异常:" + e.ToString());
            }
        }

这个线程驱动的函数里面,只要收到一个客户端的请求链接,就会再新建一个线程来收数据。有N个客户端链接,就会添加N个线程。

现在我们来实现收数据的方法ReciveMsgReqHandler

       /// 
        /// 接收客户端socket消息
        /// 
        /// 
        private void ReciveMsgReqHandler(object _socket)
        {
            Socket clientSocket = (Socket)_socket;
            try
            {
                while(true)
                {
                    //客户端连接成功后,接受来自客户端的消息
                    if (clientSocket == null)
                    {
                        continue;
                    }
                    byte[] buffer = new byte[MAX_SEND_FILE_LENGTH];  //数据缓冲区。
                    //实际接收到的有效字节数
                    //Receive也是个卡线程的方法
                    Console.WriteLine("等待接受客户端的数据:");
                    int dataLength = clientSocket.Receive(buffer);
                    Console.WriteLine("接受到客户端的数据,字节数:" + dataLength);
                    //如果客户端关闭,发送的数据就为空,就跳出循环
                    if (dataLength == 0)
                    {
                        break;
                    }
                    
                    //假设收到的是个字符串(先这么假定),转成字符串处理
                    string strMsg = Encoding.UTF8.GetString(buffer, 1, dataLength - 1);
                    Console.WriteLine("接受到客户端的消息:" + strMsg);
                }
                //中止当前线程
                Thread.CurrentThread.Abort();
            }
            catch(Exception e)
            {
                SocketException socketExp = e as SocketException;
                if (socketExp!=null && socketExp.NativeErrorCode == 10054)
                {
                    Console.WriteLine("socket客户端关闭:" + e.ToString());
                }
                else
                {
                    Console.WriteLine("======接受消息异常:" + e.ToString());
                }
                //中止当前线程
                Thread.CurrentThread.Abort();
            }
        }

就这样一个简易的socket服务器就搭建起来了。

调用方式:

SGSocketServer socketServer = new SGSocketServer();
socketServer.Start();

当然,要达到工程应用级别,还要做更多一些工作。但千里之行始于足下,有了这个基础之后就可以不断地往里面添加业务逻辑。

你可能感兴趣的:(笔记,服务器,c#,socket,websocket)