TCPClient例子(3)基于委托和事件的TcpHelper程序

如何使用

TcpHelper t;作为Form的一个成员变量。

在Form初始化的时候,初始化TcpHelper

t = new TcpHelper();
t.SetAddr("127.0.0.1", 8888);
t.connect();

同时以如下形式添加事件响应方法

t.ChannelActive += new Action<object, object>(
                (sender, arg) =>
                {
                    if (!this.IsHandleCreated||IsDisposed)
                        return;
                    this.Invoke(new MethodInvoker(
                        () =>
                        {
                            this.Text = "logged";
                        }
                        ));
                }
                );
            t.ReadComplete += new Action<object, object>(
                (sender, arg) =>
                {
                    if (!this.IsHandleCreated || IsDisposed)
                        return;
                    string info = arg as string;
                    this.Invoke(new MethodInvoker(
                        () =>
                        {
                            //MessageBox.Show(info);
                            //this.Text = info ;
                        }
                        ));
                }
                );
            t.Read += new Action<object, object>(
                (sender, arg) =>
                {
                    if (!this.IsHandleCreated || IsDisposed)
                        return;
                    string info = arg as string;
                    this.Invoke(new MethodInvoker(
                        () =>
                        {
                            //
                        }
                        ));
                }
                );
            t.ExceptionOccured += new Action<object, object>(
                (sender, arg) =>
                {
                    string info = arg as string;
                    if (!this.IsHandleCreated || IsDisposed)
                        return;
                    this.Invoke(new MethodInvoker(
                        () =>
                        {
                            this.Text = "连接异常";
                        }
                        ));
                }
                );

 在form关闭的时候

if (t != null)
{
t.close();
}

 

2.TcpHelper的源代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using LEGION.Log;
using System.Threading;
namespace LEGION.Sockets
{
    class TcpHelper
    {
        public TcpHelper()
        {
            log = AutoRefreshHtmlLog.getInstance();
            recvData = new byte[bufSize];
            reconect_worker = new Thread(reconnectThread);
            reconect_worker.IsBackground = true;
            reconect_worker.Start();
            q = new DataQ();
        }
        public TcpClient client
        {
            get;
            set;
        }
        AutoRefreshHtmlLog log;
        public bool isConnected = false;
        public event Action<object, object> ChannelActive;
        public event Action<object, object> ReadComplete;
        public event Action<object, object> Read;
        public event Action<object, object> ExceptionOccured;
        private string destination=null;
        private int port;
        AutoResetEvent do_connect = new AutoResetEvent(false);
        private Thread reconect_worker;
        private byte[] recvData;
        private const int bufSize = 2 * 1024;
        private DataQ q;
        private bool all_gone;
        public void SetAddr(string _destination,int _port){
            this.destination=_destination;
            this.port=_port;
        }
        string GetRemoteIP(TcpClient cln)
        {
            string ip = cln.Client.RemoteEndPoint.ToString().Split(':')[0];
            return ip;
        }
        public int GetRemotePort(TcpClient cln)
        {
            string temp = cln.Client.RemoteEndPoint.ToString().Split(':')[1];
            int port = Convert.ToInt32(temp);
            return port;
        }
        public void reconnectThread()
        {
            while (true)
            {
                do_connect.WaitOne();
                try
                {
                    if (!isConnected)
                    {
                        client.Close();
                        client = new TcpClient();
                        client.Connect(destination,port);
                    }
                }
                catch (Exception ex)
                {
                    log.Info("well, reconnect failed this time ,try again in five secs");
                    Thread.Sleep(5000);
                    do_connect.Set();
                    continue;
                }
                log.Info("connection re-established...\n");
                isConnected = true;
                if (ChannelActive != null)
                {
                    ChannelActive(this, "logged");
                }
                try
                {
                    client.Client.BeginReceive(recvData, 0, recvData.Length, SocketFlags.None, RecvCallBack, client);

                }
                catch (Exception ex)
                {
                    
                    log.Info(ex.ToString());
                    Thread.Sleep(5000);
                    re_establish();
                    
                }

            }
        }
        private void handleIncoming(int count)
        {
            q.CopyFromSrc(recvData, count);
            int tempFront = q.front;
            int movingFront = q.front;
            while (!(movingFront%q.handlerSize==q.rear))
            {
                if (q.handlerData[movingFront%(q.handlerSize)] == (byte)'\n'||
                    q.handlerData[movingFront%(q.handlerSize)]==(byte)'\r')
                {
                    byte[] nba = NewByteArray(q, tempFront, movingFront);
                    string pass = Encoding.UTF8.GetString(nba);
                    if (Read != null && pass.Length>0)
                    {
                        Read(this, pass);
                    }
                    tempFront = movingFront+1;
                    q.front = tempFront;
                }
                movingFront++;
            }

        }
        byte[] NewByteArray(DataQ q, int init, int end)
        {
            //remember ,init and end may exceed the size of DataQ buf
            int size = end - init;
            if (size < 0)
                size = 0;
            byte[] nba = new byte[size];
            for (int i = 0; i < end-init; i++)
            {
                nba[i] = q.handlerData[(i + init) % q.handlerSize];
            }
            return nba;
        }
        public static string StringToHexString(string s, Encoding encode)
        {
            byte[] b = encode.GetBytes(s);
            string result = string.Empty;
            for (int i = 0; i < b.Length; i++)
            {
                result += " " + b[i].ToString("X2");
            }
            return result;
        }

        public void RecvCallBack(IAsyncResult result)
        {
            int count = -1;
            try
            {
                count = client.Client.EndReceive(result);
            }
            catch (Exception ex)
            {
                log.Info(ex.ToString());
                if (ExceptionOccured != null)
                {
                    ExceptionOccured(this, ex.ToString());
                }
                re_establish();
                return;
            }
            if (count <= 0)
            {
                log.Info("receive 0 bytes,it seems the remote peer actively closes the connection.");
                if (ExceptionOccured != null)
                {
                    ExceptionOccured(this, "closes");
                }
                re_establish();
                return;
            }
            string msg = Encoding.UTF8.GetString(recvData, 0, count);
            handleIncoming(count);
            //string hs = StringToHexString(msg, Encoding.UTF8);
            //log.Info(msg);
            //log.Info(hs);
            if (ReadComplete != null)
            {
                ReadComplete(this, msg);
            }
            try
            {
          if(all_gone)
          return;
client.Client.BeginReceive(recvData,
0, recvData.Length, SocketFlags.None, RecvCallBack, client); } catch (Exception ex) { log.Info(ex.ToString()); if (ExceptionOccured != null) { ExceptionOccured(this, ex.ToString()); } re_establish(); } } private void re_establish() { log.Info("Initiating an re-opening..."); isConnected = false; do_connect.Set(); } public void connect() { client = new TcpClient(); log.Info("System Startup..."); try {client.BeginConnect(destination, port, ConnectCallBack, null); } catch (Exception ex) { log.Info(ex.ToString()); if (ExceptionOccured != null) { ExceptionOccured(this, ex.ToString()); } } } private void ConnectCallBack(IAsyncResult result) { try { client.EndConnect(result); } catch (Exception ex) { log.Info(ex.ToString()); if(ExceptionOccured !=null) ExceptionOccured(this, ex.ToString()); return; } isConnected = true; log.Info("Connected to "+GetRemoteIP(client)+" "+GetRemotePort(client)); if (ChannelActive != null) { ChannelActive(this, "logged"); } try { client.Client.BeginReceive(recvData, 0, recvData.Length, SocketFlags.None, RecvCallBack, client); } catch (Exception ex) { log.Info(ex.ToString()); if (ExceptionOccured != null) { ExceptionOccured(this, "closes"); } re_establish(); } } public void close() { try {
          all_gone=true; client.Client.Close(); }
catch (Exception ex) { log.Info(ex.ToString()); } } public void send(byte[] data, int offset, int count) { try { if (isConnected) { client.Client.BeginSend(data, offset, count, SocketFlags.None, SendCallBack, null); } } catch (Exception ex) { log.Info(ex.ToString()); if (ExceptionOccured != null) ExceptionOccured(this, "senderror"); re_establish(); } } public void SendCallBack(IAsyncResult result) { try { client.Client.EndSend(result); } catch (Exception ex) { log.Info(ex.ToString()); if (ExceptionOccured != null) ExceptionOccured(this, "senderror"); re_establish(); } } } public class DataQ { public byte[] handlerData; public int handlerSize = 10*1024; public int front, rear; public DataQ() { handlerData = new byte[handlerSize]; front = 0; rear = 0; } public bool QEmpty(){ return rear==front; } public bool QFull() { return (rear + 1) % handlerSize == front; } public int QCap()//how many bytes left to fill in { if ((rear - front) < 0) return front-rear; else return handlerSize-rear+front; } public bool CopyFromSrc(byte[] src, int count) { if (count > QCap()) { front = 0; rear = 0; return false; } else { for (int i = 0; i < count; i++) { handlerData[(rear + i) % handlerSize] = src[i]; } rear=(rear+count)%handlerSize; return true; } } } }

 AutoRefreshHtmlLog的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
/*
 * Singleton design pattern for the logger class
 */
namespace LEGION.Log
{
    public class AutoRefreshHtmlLog
    {
        private ILog logger;
        private bool lever =true;
        private static AutoRefreshHtmlLog singleton=null;
        public static AutoRefreshHtmlLog getInstance(){
            if(singleton==null){
                singleton=new AutoRefreshHtmlLog();
                return singleton;
            }
            return singleton;
        }
        public AutoRefreshHtmlLog()
        {
            logger = LogManager.GetLogger("mylogger");
            log("<meta http-equiv=\"refresh\" content=\"3\">");
        }
        public void log(string str)
        {
            if (logger.IsInfoEnabled)
            {
                logger.Info(str);
            }
        }
        public void Info(string str)
        {
            if (!lever)
                return;
            if (logger.IsInfoEnabled)
            {
                logger.Info( str + "</br>");
            }
        }

    }
}
/*
 * Additional Notes: To facilitate the use of the helper class,
 * The App.config file and code for AssemblyInfo.cs is also provided
*/

/**************************App.config**********************/
/*

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
  <log4net>
    <root>
      <level value="ALL" />
      <appender-ref ref="SysAppender" />
    </root>
    <logger name="WebLogger">
      <level value="DEBUG" />
    </logger>
    <appender name="SysAppender" type="log4net.Appender.RollingFileAppender,log4net">
      <!--<param name="File" value="App_Data/" />-->
      <param name="File" value="log\\" />
      <param name="AppendToFile" value="true" />
      <param name="RollingStyle" value="Date" />
      <param name="DatePattern" value="&quot;Logs_&quot;yyyyMMdd&quot;.html&quot;" />
      <param name="StaticLogFileName" value="false" />
      <layout type="log4net.Layout.PatternLayout,log4net">
        <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
        <param name="Header" value=" ----------------------header--------------------------&#xD;&#xA;" />
        <param name="Footer" value=" ----------------------footer--------------------------&#xD;&#xA;" />
      </layout>
    </appender>
    <appender name="consoleApp" type="log4net.Appender.ConsoleAppender,log4net">
      <layout type="log4net.Layout.PatternLayout,log4net">
        <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
      </layout>
    </appender>
  </log4net>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
</configuration>

*/


/******************************AssemblyInfo.cs**************************/
/*

[assembly: log4net.Config.XmlConfigurator(ConfigFileExtension="config",Watch=true)]
*/

 

  

posted on 2018-06-25 11:57  legion  阅读(810)  评论(0编辑  收藏  举报

导航