TcpClient.cs 8.3 KB
using DL.Utils;
using log4net;
using System;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading;

namespace DL.Com.TCP
{
    public class TcpClient
    {
        public delegate void HandleMessage(string message, byte[] data);

        private Socket m_clientSocket = null;
        private byte[] m_receiveBuffer = new byte[1024];

        private HandleMessage onReceived;
        public int TimeOutTime = 2;
        public string IP { get; set; }
        public int Port { get; set; }
        public TcpClient()
        {
           
        }
        /// <summary>
        ///  当前连接状态
        /// </summary> 
        public bool IsConnected()
        {
            if (m_clientSocket == null)
            {
                return false;
            }
            return m_clientSocket.Connected;
            //if (m_clientSocket.Connected)
            //{
            //    return true;
            //}
            #region remarks
            /********************************************************************************************
         * 当Socket.Conneted为false时, 如果您需要确定连接的当前状态,请进行非阻塞、零字节的 Send 调用。
         * 如果该调用成功返回或引发 WAEWOULDBLOCK 错误代码 (10035),则该套接字仍然处于连接状态; 
         * 否则,该套接字不再处于连接状态。
         * Depending on http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.connected.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2
        ********************************************************************************************/
            #endregion
            try
            {
                #region 过程
                // This is how you can determine whether a socket is still connected.
                bool connectState = true;
                bool blockingState = m_clientSocket.Blocking;
                try
                {
                    byte[] tmp = new byte[1];

                    m_clientSocket.Blocking = false;
                    m_clientSocket.Send(tmp, 0, 0);
                    //Console.WriteLine("Connected!");
                    connectState = true; //若Send错误会跳去执行catch体,而不会执行其try体里其之后的代码
                }
                catch (SocketException e)
                {
                    // 10035 == WSAEWOULDBLOCK
                    if (e.NativeErrorCode.Equals(10035))
                    {
                        connectState = true;
                    }
                    else
                    {
                        connectState = false;
                    }
                }
                finally
                {
                    if (m_clientSocket != null && m_clientSocket.Connected)
                    {
                        m_clientSocket.Blocking = blockingState;
                    }
                }

                //Console.WriteLine("Connected: {0}", client.Connected);
                return connectState;
                #endregion
            }
            catch (Exception ex)
            {
                //Log.Error("IsConnected 出错", log, ex);
                return false;
            }
        }
        /// <summary>
        /// 连接服务器
        /// </summary>
        public bool Connect(string serverIP, int serverPort, HandleMessage HandleMessage)
        {
            IP=serverIP;
            Port=serverPort;
            m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            if (TimeOutTime <= 0)
            {
                IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(serverIP), serverPort);
                m_clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                try
                {
                    if (!m_clientSocket.Connected)
                    {
                        m_clientSocket.Connect(remoteEndPoint);
                    }
                    if (m_clientSocket.Connected)
                    {
                        m_clientSocket.BeginReceive(m_receiveBuffer, 0, m_receiveBuffer.Length, 0, new AsyncCallback(ReceiveCallBack), null);
                        onReceived = HandleMessage;
                        LogUtil.Info("Connect to " + serverIP + ":" + serverPort + " success!");
                        return true;
                    }
                    else
                    {
                        LogUtil.Info("Connect to " + serverIP + ":" + serverPort + " fail!");
                    }
                }
                catch (Exception ex)
                {
                    LogUtil.Error("Connect to " + serverIP + ":" + serverPort + " fail!", ex);
                    //m_clientSocket = null;
                }
            }
            else
            {
                m_clientSocket.ReceiveTimeout = TimeOutTime;
                m_clientSocket.SendTimeout = TimeOutTime;
                IAsyncResult connResult = m_clientSocket.BeginConnect(serverIP, serverPort, null, null);

                connResult.AsyncWaitHandle.WaitOne(this.TimeOutTime, true);  //等待2秒

                if (!connResult.IsCompleted || (!m_clientSocket.Connected))
                {
                    LogUtil.Info("Connect to " + serverIP + ":" + serverPort + " fail!");
                    m_clientSocket.Close();
                    //处理连接不成功的动作
                    return false;
                }
                else
                {
                    //处理连接成功的动作
                    m_clientSocket.BeginReceive(m_receiveBuffer, 0, m_receiveBuffer.Length, 0, new AsyncCallback(ReceiveCallBack), null);
                    onReceived = HandleMessage;
                    LogUtil.Info("Connect to " + serverIP + ":" + serverPort + " success!");
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public void Close()
        {
            try
            {
                if (m_clientSocket != null && m_clientSocket.Connected)
                {
                    m_clientSocket.Shutdown(SocketShutdown.Both);
                    //Thread.Sleep(300);
                    //m_clientSocket.Disconnect(true);
                    //Thread.Sleep(300);
                    m_clientSocket.Close();
                    //m_clientSocket = null;
                    LogUtil.Info("Socket closed!");

                }
                else
                {
                    LogUtil.Error("No socket is running!");
                }
            }
            catch (Exception ex)
            {
                LogUtil.Error("close error", ex);
            }
        }

        /// <summary>
        /// 发送信息
        /// </summary>
        public void Send(string strSendData)
        {
            byte[] sendBuffer = new byte[1024];
            sendBuffer = Encoding.UTF8.GetBytes(strSendData);

            if (m_clientSocket != null && m_clientSocket.Connected)
            {
                m_clientSocket.Send(sendBuffer);
                LogUtil.Debug("Send >> " + strSendData);
            }
        }
        public bool Send(byte[] bytes)
        {
           if (m_clientSocket != null && m_clientSocket.Connected)
            {
                m_clientSocket.Send(bytes);
                LogUtil.Debug("Send >> " + StringHelper.ToHexString(bytes));
                return true;
            }
            return false;
        }
        private void ReceiveCallBack(IAsyncResult ar)
        {
            try
            {
                if (m_clientSocket != null && m_clientSocket.Connected)
                {
                    int REnd = m_clientSocket.EndReceive(ar);
                    string strReceiveData = Encoding.Default.GetString(m_receiveBuffer, 0, REnd);
                    byte[] tmp = new byte[REnd];
                    Array.Copy(m_receiveBuffer, tmp, REnd);
                    onReceived(strReceiveData, tmp);
                    Thread.Sleep(100);
                    m_clientSocket.BeginReceive(m_receiveBuffer, 0, m_receiveBuffer.Length, 0, new AsyncCallback(ReceiveCallBack), null);
                }
            }
            catch (Exception ex)
            {
                LogUtil.Error("socket received error", ex);
            }
        }
    }
}