zoukankan      html  css  js  c++  java
  • 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...
    ");
                    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)'
    '||
                        q.handlerData[movingFront%(q.handlerSize)]==(byte)'
    ')
                    {
                        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)]
    */

      

  • 相关阅读:
    [转]浏览器退出之后php还会继续执行么?
    vim常用命令
    [转]自己写PHP扩展之创建一个类
    [转]用C/C++扩展PHP详解
    [转]PHP的执行流程,PHP扩展加载过程
    用扩展开发一个PHP类
    gcc
    Linux常用网络命令
    TCP-IP详解学习笔记1
    在Linux中调试段错误(core dumped)
  • 原文地址:https://www.cnblogs.com/legion/p/9223738.html
Copyright © 2011-2022 走看看