c# 多线程同步socket判断异常

相信大家和我一样刚接触socket编程时纠结于tcp的客户端异常断开该如何处理吧?下面我就告诉你们一个简单的方法,不算优雅但是能用!为何不优雅?因为用的是同步socket + 多线程也就是说每当有客户端连接进程就要创建一个新的线程...所以当有几百人同时连接的时候处理器要不断的切换线程从而影响了性能。

原理就是通过手动设置time_out->抛出异常->捕捉异常,性能一般4核处理器同时处理300个链接左右(测试环境:300客户端同时链接每0.1秒发送一个随机字符串服务器储蓄到数据库中。如果只是当聊天室的话2000个应该不是问题)

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;


public class TcpServer
{
    private Socket _tcp_srv = null;
    private List<User> users = null;

    // 初始化 socket 和 user 集
    public TcpServer(IPEndPoint iep)
    {
        users = new List<User>();
        _tcp_srv = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        _tcp_srv.Bind(iep);
        _tcp_srv.Listen(64);
    }

    // 启动SQLiteServer
    public void Start()
    {
        // 监听线程
        Thread Listenner = new Thread(OnNewSession);
        Listenner.Start();
    }

    // 停止监听
    public void Stop()
    {
        _tcp_srv.Close();
        _tcp_srv = null;
    }

    // 处理新客户端过程
    private void OnNewSession()
    {
        while (true)
        {
            try
            {
                Socket client_socket = _tcp_srv.Accept();
                if (client_socket == null) return;

                User u = new User();
                u.socket = client_socket;
                lock (users)
                {
                    users.Add(u);
                }

                Thread receiveThread = new Thread(OnReceive);
                receiveThread.Start(u);
            }
            catch
            {
                break;// 如果client->socket.close()
            }
        }
    }

    // 处理收到的消息
    private void OnReceive(object param)
    {
        User client = (User)param;
        if (client == null) return;

        while (true)
        {
            try
            {
                // 设置120 秒内没有数据传输则抛出异常
                client.socket.ReceiveTimeout = 1000 * 120;

                byte[] msg = new byte[1024];

                int n = client.socket.Receive(msg);
                if (n == 0) throw new Exception("close by client");

                Console.WriteLine(Encoding.UTF8.GetString(msg, 0, n));

                byte[] se = Encoding.UTF8.GetBytes(DateTime.Now.ToLongTimeString());
                client.socket.Send(se);
            }
            catch
            {
                // 抛出异常
                // 这里处理用户连接超时,连接断开,拔掉网线
                client.socket.Shutdown(SocketShutdown.Both);
                client.socket.Close();
                lock (users)
                {
                    users.Remove(client);
                }
                break;
            }
        }
    }
}

发表评论