Socket 服务端

        以前写过一个Socket服务端程序,但在写4G模块项目的时候,遇到了一个问题,就是在服务端断开Socket客户端连接后,客户端收不到断开的状态,而且使用异步时,明明服务端停止服务了,但是客户端的连接依然还在,只不过不接收数据了,但客户端和服务端的连接照样还是在进行,所以花费了一天时间,继续研究Socket机制,写了一个服务端程序,这个程序不仅可以统计客户端数量,而且可以对收到的消息,发送的消息,断开的连接,接收的客户端做出事件,供外部访问,本来想做成COM控件,但想来没有什么用,没做,下面是代码,分享给大家,如果有更好的意见或建议,欢迎留言:

事件类:

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

namespace TcpLibrary
{
    public sealed class AcceptClient
    {
        /// <summary>
        /// 连接的客户端
        /// </summary>
        public Socket Client
        { get; set; }
        /// <summary>
        /// 连接地址
        /// </summary>
        public string Address
        { get; set; }
        /// <summary>
        /// 连接端口号
        /// </summary>
        public int Port
        { get; set; }
        /// <summary>
        /// SocketID
        /// </summary>
        public IntPtr ClientID
        { get; set; }
    }
    /// <summary>
    /// 接收客户端事件
    /// </summary>
    public sealed class AcceptClientEventArgs : EventArgs
    {
        /// <summary>
        /// 收到的客户端
        /// </summary>
        public Socket Client
        { get; set; }
        /// <summary>
        /// 收到的客户端
        /// </summary>
        public IPEndPoint EndPointRemote
        { get; set; }
        /// <summary>
        /// 收到的地址
        /// </summary>
        public IPAddress IPAddressRemote
        { get; set; }
        /// <summary>
        /// 收到客户端连接的端口号
        /// </summary>
        public int Port
        { get; set; }
    }
    /// <summary>
    /// 收到客户端发送过来的数据
    /// </summary>
    public sealed class ReceivedBufferEventArgs : EventArgs
    {
        /// <summary>
        /// 客户端来源
        /// </summary>
        public IPEndPoint EndPointRemote
        { get; set; }
        /// <summary>
        /// 来源客户端连接
        /// </summary>
        public Socket Client
        { get; set; }
        /// <summary>
        /// 收到的客户数据
        /// </summary>
        public byte[] Buffer
        { get; set; }
    }

    public sealed class HostDisconnectEventArgs : EventArgs
    {
        /// <summary>
        /// 客户端来源
        /// </summary>
        public IPEndPoint EndPointRemote
        { get; set; }
        /// <summary>
        /// 客户端来源地址
        /// </summary>
        public string Address
        { get; set; }
        /// <summary>
        /// 客户端来源端口号
        /// </summary>
        public int Port
        { get; set; }
        /// <summary>
        /// 客户端来源句柄
        /// </summary>
        public IntPtr ClientID
        { get; set; }
        /// <summary>
        /// 来源客户端连接
        /// </summary>
        public Socket Client
        { get; set; }
    }
}
委托类:

using System;
using System.Collections.Generic;
using System.Text;

namespace TcpLibrary
{
    /// <summary>
    /// 接收客户端事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void AcceptClientEvents(object sender, AcceptClientEventArgs e);
    /// <summary>
    /// 接收数据事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void ReceiveBufferEvents(object sender, ReceivedBufferEventArgs e);
    /// <summary>
    /// 断开客户端连接事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void HostDisconnectionEvents(object sender, HostDisconnectEventArgs e);
}
数据接收类:

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

namespace TcpLibrary
{
    /// <summary>
    /// Socket数据接收类
    /// </summary>
    public sealed class TcpReceive
    {
        private byte[] _Buffer = new byte[2048];
        /// <summary>
        /// 获取或设置接收的数据信息
        /// </summary>
        public byte[] Buffer
        {
            get { return _Buffer; }
            set { _Buffer = value; }
        }
        private Socket _Client;
        /// <summary>
        /// 获取或设置连接的客户端
        /// </summary>
        public Socket Client
        {
            get { return _Client; }
            set { _Client = value; }
        }
    }
}
服务端监听类:

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

namespace TcpLibrary
{
    /// <summary>
    /// 监听类
    /// </summary>
    public sealed class TCPListener
    {
        
        public static ManualResetEvent allDone = new ManualResetEvent(false);
        private Socket tcpListener;
        /// <summary>
        /// 收到客户端事件
        /// </summary>
        public event AcceptClientEvents AcceptClientEvent;
        /// <summary>
        /// 收到消息事件
        /// </summary>
        public event ReceiveBufferEvents ReceivedBufferEvent;
        /// <summary>
        /// 断开连接事件
        /// </summary>
        public event HostDisconnectionEvents DisconnectionEvent;
        private List<Thread> listThread = new List<Thread>();
        private List<AcceptClient> listClient = new List<AcceptClient>();
        private object objClientList = new object();
        /// <summary>
        /// 获取连接的客户端集合
        /// </summary>
        public List<AcceptClient> Clients
        {
            get { return listClient; }
        }
        private int Port;
        /// <summary>
        /// 获取或设置接收超时时间(秒)
        /// </summary>
        public int? ReceiveTimeOut
        { get; set; }
        /// <summary>
        /// 获取或设置发送超时时间(秒)
        /// </summary>
        public int? SendTimeOut
        { get; set; }
        public TCPListener(int Port)
        {
            this.Port = Port;
        }

        private bool IsStartListener = false;

        public void Start()
        {
            tcpListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            tcpListener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            IPEndPoint point = new IPEndPoint(IPAddress.Parse("0.0.0.0"), Port);
            tcpListener.Bind(point);
            tcpListener.Listen(2000);
            IsStartListener = true;
            Thread thread = new Thread(new ThreadStart(ClientAcceptAsync));
            thread.Start();
            listThread.Add(thread);
        }

        private void ClientAcceptAsync()
        {
            while (IsStartListener)
            {
                try
                {
                    TcpReceive receive = new TcpReceive();
                    receive.Client = tcpListener.Accept();
                    if (receive.Client.Connected)
                    {
                        //listClient.Add(receive.Client);
                        IPEndPoint point = receive.Client.RemoteEndPoint as IPEndPoint;
                        lock (objClientList)
                        {
                            AcceptClient ac = new AcceptClient();
                            ac.ClientID = receive.Client.Handle;
                            ac.Client = receive.Client;
                            ac.Address = point.Address.ToString();
                            ac.Port = point.Port;
                            listClient.Add(ac);
                        }
                        AcceptClientEventArgs e = new AcceptClientEventArgs();
                        e.Client = receive.Client;
                        e.EndPointRemote = point;
                        e.IPAddressRemote = e.EndPointRemote.Address;
                        e.Port = e.EndPointRemote.Port;
                        if (AcceptClientEvent != null)
                            AcceptClientEvent.Invoke(receive, e);
                        //receive.Client.BeginReceive(receive.Buffer, 0, receive.Buffer.Length, SocketFlags.None, new AsyncCallback(Receive), receive);
                        if(ReceiveTimeOut != null)
                            receive.Client.ReceiveTimeout = 1000 * Convert.ToInt32(ReceiveTimeOut);
                        if(SendTimeOut != null)
                            receive.Client.SendBufferSize = 1000 * Convert.ToInt32(SendTimeOut);
                        Thread thread = new Thread(new ParameterizedThreadStart(Receive));
                        thread.Start(receive);
                        listThread.Add(thread);
                    }
                    Thread.Sleep(100);
                }
                catch (Exception ex)
                {
                    break;
                }
            }
        }

        private void RemoveClient(AcceptClient ac)
        {
            for (int i = 0; i < listClient.Count; i++)
            {
                if (listClient[i].ClientID == ac.ClientID)
                {
                    try
                    {
                        listClient[i].Client.Shutdown(SocketShutdown.Both);
                    }
                    catch
                    { }
                    finally
                    {
                        listClient[i].Client.Close();
                    }
                    listClient.RemoveAt(i);
                    break;
                }
            }
        }

        private void Receive(object sender)
        {
            TcpReceive receive = sender as TcpReceive;
            HostDisconnectEventArgs e = new HostDisconnectEventArgs();
            e.Client = receive.Client;
            e.ClientID = receive.Client.Handle;
            e.EndPointRemote = receive.Client.RemoteEndPoint as IPEndPoint;
            e.Address = e.EndPointRemote.Address.ToString();
            e.Port = e.EndPointRemote.Port;
            AcceptClient ac = new AcceptClient();
            ac.Client = receive.Client;
            ac.Address = e.EndPointRemote.Address.ToString();
            ac.Port = e.EndPointRemote.Port;
            ac.ClientID = receive.Client.Handle;
            while (IsStartListener)
            {
                try
                {
                    if (!receive.Client.Connected)
                    {
                        e.Client = receive.Client;
                        if (DisconnectionEvent != null)
                            DisconnectionEvent.Invoke(this, e);
                        RemoveClient(ac);
                        try
                        {
                            receive.Client.Shutdown(SocketShutdown.Both);
                        }
                        catch { }
                        finally
                        {
                            receive.Client.Close();
                        }
                        break;
                    }
                    int byteRead = receive.Client.Receive(receive.Buffer, 0, receive.Buffer.Length, SocketFlags.None);
                    if (byteRead > 0)
                    {
                        ReceivedBufferEventArgs re = new ReceivedBufferEventArgs();
                        re.Buffer = new byte[byteRead];
                        Array.Copy(receive.Buffer, re.Buffer, byteRead);
                        re.Client = receive.Client;
                        IPEndPoint point = receive.Client.RemoteEndPoint as IPEndPoint;
                        re.EndPointRemote = point;
                        if (ReceivedBufferEvent != null)
                            ReceivedBufferEvent.Invoke(receive, re);
                    }
                    else
                    {
                        e.Client = receive.Client;
                        if (DisconnectionEvent != null)
                            DisconnectionEvent.Invoke(receive, e);
                        RemoveClient(ac);
                        try
                        {
                            receive.Client.Shutdown(SocketShutdown.Both);
                        }
                        catch { }
                        finally
                        {
                            receive.Client.Close();
                        }
                        break;
                    }
                }
                catch
                {
                    try
                    {
                        receive.Client.Shutdown(SocketShutdown.Both);
                    }
                    catch { }
                    finally
                    {
                        receive.Client.Close();
                    }
                    RemoveClient(ac);
                    if (DisconnectionEvent != null)
                        DisconnectionEvent.Invoke(receive, e);
                    break;
                }
            }
        }

        public void Send(Socket Client, byte[] buffer)
        {
            if (!IsStartListener)
            {
                try
                {
                    Client.Shutdown(SocketShutdown.Both);
                }
                catch { }
                finally
                {
                    Client.Close();
                }
                return;
            }
            if(Client.Connected)
                Client.Send(buffer);
        }

        public void Stop()
        {
            IsStartListener = false;
            try
            {
                //tcpListener.Shutdown(SocketShutdown.Both);
                tcpListener.Close();
            }
            catch { }
            tcpListener = null;
            for (int i = 0; i < listClient.Count; i++)
            {
                try
                {
                    listClient[i].Client.Shutdown(SocketShutdown.Both);
                }
                catch { }
                finally
                {
                    listClient[i].Client.Close();
                }
            }
            for (int i = 0; i < listThread.Count; i++)
            {
                try
                {
                    listThread[i].Abort();
                    //while (!(listThread[i].ThreadState == ThreadState.Aborted) && !(listThread[i].ThreadState == ThreadState.Stopped))
                    //{
                    //    Thread thread = listThread[i];
                    //    thread.Abort();
                    //    if (thread.ThreadState == ThreadState.Aborted || thread.ThreadState == ThreadState.Stopped)
                    //    {
                    //        thread.Abort();
                    //        break ;
                    //    }
                    //}
                }
                catch { }
            }
            listClient.Clear();
            listThread.Clear();
        }
    }
}
以上是全部代码,留做记忆或大家写的时候,可以做一 个参考,不用再绕圈子。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值