C#socket

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Net.Sockets;
using System.Net;
using System.IO;

namespace TcpSvr
{
    public class TcpCli
    {
        #region 字段
        /// <summary>
        /// 客户端与服务器之间的会话类
        /// </summary>
        private Session _session;
        /// <summary>
        /// 客户端是否已经连接服务器
        /// </summary>
        private bool _isConnected = false;
        /// <summary>
        /// 接收数据缓冲区大小64K
        /// </summary>
        public const int DefaultBufferSize = 64 * 1024;
        /// <summary>
        /// 报文解析器
        /// </summary>
        private DatagramResolver _resolver;

        /// <summary>
        /// 接收数据缓冲区
        /// </summary>
        private byte[] _recvDataBuffer = new byte[DefaultBufferSize];
        #endregion
        #region 事件定义
        //需要订阅事件才能收到事件的通知,如果订阅者退出,必须取消订阅

        /// <summary>
        /// 已经连接服务器事件
        /// </summary>
        public event NetEvent ConnectedServer;
        /// <summary>
        /// 接收到数据报文事件
        /// </summary>
        public event NetEvent ReceivedDatagram;
        /// <summary>
        /// 连接断开事件
        /// </summary>
        public event NetEvent DisConnectedServer;
        /// <summary>
        /// 连接失败
        /// </summary>
        public event NetEvent ConnectedServerFail;
        #endregion
        #region 属性
        /// <summary>
        /// 返回客户端与服务器之间的会话对象
        /// </summary>
        public Session ClientSession
        {
            get
            {
                return _session;
            }
        }
        /// <summary>
        /// 返回客户端与服务器之间的连接状态
        /// </summary>
        public bool IsConnected
        {
            get
            {
                return _isConnected;
            }
        }
        /// <summary>
        /// 数据报文分析器
        /// </summary>
        public DatagramResolver Resovlver
        {
            get
            {
                return _resolver;
            }
            set
            {
                _resolver = value;
            }
        }

        #endregion

        #region 公有方法

        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <param name="ip">服务器IP地址</param>
        /// <param name="port">服务器端口</param>
        public virtual void Connect(string ip, int port)
        {

            if (IsConnected)
            {
                //重新连接
                Debug.Assert(_session != null);
                Close();
            }
            Socket newsock = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint iep = new IPEndPoint(IPAddress.Parse(ip), port);
            newsock.BeginConnect(iep, new AsyncCallback(Connected), newsock);


        }
        /// <summary>
        /// 发送数据报文
        /// </summary>
        /// <param name="datagram"></param>
        public virtual void Send(byte[] data, Cmd cmds)
        {
            if (data.Length == 0)
            {
                return;
            }
            if (!_isConnected)
            {
                throw (new ApplicationException("没有连接服务器,不能发送数据"));
            }
            DatagramResolver datasend = new DatagramResolver(data, cmds);


            _session.ClientSocket.BeginSend(datasend.Tobytes, 0, datasend.Tobytes.Length, SocketFlags.None,
            new AsyncCallback(SendDataEnd), _session.ClientSocket);

        }
        /// <summary>
        /// 关闭连接
        /// </summary>
        public virtual void Close()
        {
            if (!_isConnected)
            {
                return;
            }
            _session.Close();
            _session = null;
            _isConnected = false;
        }
        #endregion
        #region 受保护方法
        /// <summary>
        /// 数据发送完成处理函数
        /// </summary>
        /// <param name="iar"></param>
        protected virtual void SendDataEnd(IAsyncResult iar)
        {
            Socket remote = (Socket)iar.AsyncState;
            int sent = remote.EndSend(iar);
            Debug.Assert(sent != 0);
        }
        /// <summary>
        /// 建立Tcp连接后处理过程
        /// </summary>
        /// <param name="iar">异步Socket</param>
        protected virtual void Connected(IAsyncResult iar)
        {
            try
            {
                Socket socket = (Socket)iar.AsyncState;
                socket.EndConnect(iar);
                //创建新的会话
                _session = new Session(socket);

                _isConnected = true;
                _resolver = new DatagramResolver();
                //触发连接建立事件
                if (ConnectedServer != null)
                {
                    ConnectedServer(this, new NetEventArgs(_session));
                }
                //建立连接后应该立即接收数据
                _session.ClientSocket.BeginReceive(_recvDataBuffer, 0,
                DefaultBufferSize, SocketFlags.None,
                new AsyncCallback(RecvData), socket);

            }
            catch (SocketException) {
                if (ConnectedServerFail != null)
                {
                    ConnectedServerFail(this, null);

                }
            
            }
        }


        /// <summary>
        /// 数据接收处理函数
        /// </summary>
        /// <param name="iar">异步Socket</param>
        protected virtual void RecvData(IAsyncResult iar)
        {
            Socket client = (Socket)iar.AsyncState;
            try
            {
                int recv = client.EndReceive(iar);
                if (recv == 0)
                {
                    _session.TypeOfExit = Session.ExitType.NormalExit;
                    if (DisConnectedServer != null)
                    {
                        DisConnectedServer(this, new NetEventArgs(_session));
                    }
                    return;
                }
                if (_resolver.Resolver(ref _session, _recvDataBuffer))
                {
                    _session.RecvDataLength = 0;
                    _session.TotalDataLength = 8;
                    if (ReceivedDatagram != null)
                    {
                        ICloneable copySession = (ICloneable)_session;
                        Session clientSession = (Session)copySession.Clone();


                        //发布一个报文消息
                        //   Array.Clear(_recvDataBuffer,0,DefaultBufferSize);
                        ReceivedDatagram(this, new NetEventArgs(clientSession));
                    }
                }



                client.BeginReceive(_recvDataBuffer, 0, _recvDataBuffer.Length, SocketFlags.None,
       new AsyncCallback(RecvData), client);

            }
            catch (SocketException ex)
            {
                //客户端退出
                if (10054 == ex.ErrorCode)
                {
                    //服务器强制的关闭连接,强制退出

                    _session.TypeOfExit = Session.ExitType.ExceptionExit;
                    if (DisConnectedServer != null)
                    {
                        DisConnectedServer(this, new NetEventArgs(_session));
                    }
                }
                else
                {
                    throw (ex);
                }
            }
            catch (ObjectDisposedException ex)
            {

                if (ex != null)
                {
                    ex = null;
                    //DoNothing;
                }
            }
        }

        #endregion
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值