⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpsockets.cs

📁 是一个简易的聊天系统
💻 CS
字号:
using System;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Text;
using System.Data;
using System.Runtime.InteropServices;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections.Generic;
using System.Configuration;

namespace Utility
{
    /// <summary> 
    /// 网络通讯事件模型委托 
    /// </summary> 
    public delegate void NetEvent(object sender, NetEventArgs e);
    public delegate void StateEvent(object sender, StateEventArgs e);

    /// <summary>
    /// Tcp服务器端 
    /// </summary>
    public class TcpServer
    {
        #region 字段
        private int _maxClients = 1000;
        private int _port;
        private string _IP = "0.0.0.0";
        private Socket svrSock;
        #endregion

        #region 事件定义
        /// <summary> 
        /// 客户端建立连接事件 
        /// </summary> 
        public event NetEvent ClientConn;
        public event NetEvent UnLink;
        #endregion

        #region 构造函数
        /// <summary> 
        /// 鉴于Internet上的标准MTU值为576字节,所以我建议在进行Internet的UDP编程时.最好将UDP的数据长度控件在548字节(576-8-20)以内.TCP:576-20-20=536 
        /// 构造函数,默认IP及容纳能力
        /// </summary> 
        public TcpServer() 
        {
            this._port = int.Parse(ConfigurationManager.AppSettings["port"]);
        }

        #endregion

        #region 公用方法

        /// <summary> 
        /// 启动服务器程序,开始监听客户端请求 
        /// </summary> 
        public virtual void Start()
        {
            svrSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint iep = new IPEndPoint(IPAddress.Parse(this._IP), this._port);
            svrSock.Bind(iep);
            svrSock.Listen(this._maxClients);
            svrSock.BeginAccept(new AsyncCallback(AcceptCallback), svrSock);
        }
        /// <summary>
        /// 停止服务器程序,还有问题
        /// </summary>
        public virtual void Stop()
        {
            try
            {
                svrSock.Close();
            }
            catch (Exception ex)
            {
                //Console.WriteLine(ex.Message);
            }
        }
        #endregion

        #region 受保护的方法
        protected virtual void AcceptCallback(IAsyncResult iar)
        {
            Socket oldserver = (Socket)iar.AsyncState;
            Socket client = oldserver.EndAccept(iar);

            TcpHelper helper = new TcpHelper(client);

            //client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, 1);
            //uint dummy = 0;
            //byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
            //BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
            //BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
            //BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
            //byte[] OUT = new byte[4];
            //int recode = client.IOControl(IOControlCode.KeepAliveValues, inOptionValues, OUT);
            //recode = OUT[0] + OUT[1] + OUT[2] + OUT[3];
            //if (recode != 0)
            //{
            //    if (this.UnLink != null)
            //        this.UnLink(this, new NetEventArgs(helper));
            //    return;
            //}
            client.BeginReceive(helper.Buffer, 0, helper.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveData), helper);
            if (ClientConn != null)
                ClientConn(this, new NetEventArgs(helper));
            oldserver.BeginAccept(new AsyncCallback(AcceptCallback), oldserver);
        }

        protected virtual void ReceiveData(IAsyncResult th)
        {
            TcpHelper helper = (TcpHelper)th.AsyncState;
            Socket server = helper.ClientSocket;
            try
            {
                int bytelong = server.EndReceive(th);
                if (bytelong == 0)
                {
                    if (this.UnLink != null)
                        this.UnLink(this, new NetEventArgs(helper));
                    helper = null;
                    return;
                }
                helper.Receive(bytelong);
                server.BeginReceive(helper.Buffer, 0, helper.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveData), helper);
            }
            catch (Exception ex)
            {
                if (this.UnLink != null)
                    this.UnLink(this, new NetEventArgs(helper));
                helper = null;
            }
        }
        #endregion
    }
    [Serializable]
    public class TcpHelper
    {
        #region 字段
        /// <summary>
        /// 单包大小 
        /// </summary>
        private const int _bagSize = 2048;
        /// <summary>
        /// 缓冲器
        /// </summary>
        private byte[] _buffer;

        private Socket _clientSocket;

        /// <summary>
        /// 最后一次动作的时间
        /// </summary>
        private DateTime _lastTime;
        private Timer _timer;
        private string _bak;

        #endregion 

        #region 属性
        /// <summary>
        /// 缓冲器中数据
        /// </summary>
        public byte[] Buffer
        {
            set { this._buffer = value; }
            get { return this._buffer; }
        }

        /// <summary>
        /// 连接上来的
        /// </summary>
        public Socket ClientSocket 
        {
            get { return this._clientSocket; }
        }

        //单包大小,应用层可以用的数据单包大小
        public int BagSize 
        {
            get { return _bagSize/2; }
        }

        /// <summary>
        /// 备用属性
        /// </summary>
        public string Bak 
        {
            get { return _bak; }
            set { _bak = value; }
        }
        #endregion

        #region 事件定义
        /// <summary> 
        /// 接收数据事件 
        /// </summary> 
        public event StateEvent ReceiveInfo;
        #endregion

        #region 构造函数
        public TcpHelper(Socket client)
        {
            this._clientSocket = client;
            this._buffer = new byte[4096];
            _lastTime = DateTime.Now;
            _timer = new Timer(new TimerCallback(this.ping), null, 10000, 10000);
        }
        private void ping(Object stateInfo) 
        {
            
            long m = (DateTime.Now.Ticks - _lastTime.Ticks) / 10000;
            if (m > 2 * 60 * 1000)
            {
                _clientSocket.Close();
            }
            if (m > 60 * 1000) 
            {
                byte[] data = new byte[_bagSize];
                data[0] = (byte)DataType.Ping;
                this.SendSyn(data);
            }
        }
        #endregion

        #region 接收任务 

        /// <summary>
        /// 把垃圾清理掉
        /// </summary>
        /// <param name="bytelong">真正的大小</param>
        public void Receive(int bytelong)
        {
            byte[] realData = new byte[bytelong];
            Array.Copy(this._buffer, realData, bytelong);

            _lastTime = DateTime.Now;

            
            if (this.ReceiveInfo != null && realData[0] < 0xF0)
                this.ReceiveInfo(this, new StateEventArgs(realData));

            
        }

        #endregion

        #region 发送任务
        /// <summary>
        /// 发送字符串,通过异步的方式
        /// </summary>
        /// <param name="content"></param>
        public bool SendAsync(byte[] data)
        {
            if (!this._clientSocket.Connected) return false;
            this._clientSocket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendEnd), data);
            return true;
        }

        protected virtual void SendEnd(IAsyncResult iar)
        {
            try
            {
                int sent = this._clientSocket.EndSend(iar);
            }
            catch { }
        }

        /// <summary>
        /// 发送同步字符串
        /// </summary>
        /// <param name="content">字符串</param>
        /// <returns>是否成功</returns>
        public bool SendSyn(byte[] data)
        {
            if (!this._clientSocket.Connected) return false;
            this._clientSocket.Send(data, 0, data.Length, SocketFlags.None);
            return true;
        }










        #endregion




 

        public void Dispose()
        {
            this._bak = null;
            this._buffer = null;
            if (this._clientSocket != null)
                this._clientSocket.Close(1);
            this.ReceiveInfo = null;
            _timer.Dispose();
            _timer = null;
            this._clientSocket = null;
            
        }

   
    }
    public class NetEventArgs : EventArgs
    {

        #region 字段
        /// <summary> 
        /// 客户端与服务器之间的会话 
        /// </summary> 
        private TcpHelper _client;
        #endregion

        #region 构造函数
        /// <summary> 
        /// 构造函数 
        /// </summary> 
        /// <param name="client">客户端会话</param> 
        public NetEventArgs(TcpHelper client)
        {
            if (client == null)
            {
                throw (new ArgumentNullException());
            }
            _client = client;
        }
        #endregion

        #region 属性

        /// <summary> 
        /// 获得激发该事件的会话对象 
        /// </summary> 
        public TcpHelper Client
        {
            get { return _client; }
        }
        #endregion

    }
    public class StateEventArgs : EventArgs
    {

        #region 字段
        /// <summary> 
        /// 客户端与服务器之间的会话 
        /// </summary> 
        private byte[] _data;
        #endregion

        #region 构造函数
        /// <summary> 
        /// 构造函数 
        /// </summary> 
        /// <param name="client">客户端会话</param> 
        public StateEventArgs(byte[] data)
        {
            _data = data;
        }
        #endregion

        #region 属性
        /// <summary> 
        /// 获得激发该事件的会话对象 
        /// </summary> 
        public byte[] Data
        {
            get { return _data; }
        }
        #endregion
    }

    /// <summary>
    /// 系统自用数据类型,值大于等于0XF0
    /// </summary>
    public enum DataType
    {
        /// <summary>
        /// SOCKET自用
        /// </summary>
        SocketUsed = 0xF0,
        /// <summary>
        /// 服务器端测试连接状态
        /// </summary>
        Ping = 0xF1,
        /// <summary>
        /// 建立一个分包发送对象,由SOCKETHELPER组合后返给应用层,这种方式不接受>(BagSize-3)*255的数据包
        /// 这是一种轻量级的分包,如果要传文件之类的功能,另行实现
        /// </summary>
        SendPack = 0xF2,
        /// <summary>
        /// 表示当前的数据为分包发送数据,byte[1] byte[2] 记录是第几个包,长度为255*255,255为进制,因为这轻量级,所以,最大限制为20*255,大约2.7MB
        /// </summary>
        SendPark = 0xF3,
        /// <summary>
        /// 建立接收分包
        /// </summary>
        ReceivePack = 0xF4,
        /// <summary>
        /// 每一个分包
        /// </summary>
        ReceivePark = 0xF5
    }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -