码迷,mamicode.com
首页 > Windows程序 > 详细

C# TCPClient开发手记

时间:2017-11-01 20:26:51      阅读:264      评论:0      收藏:0      [点我收藏+]

标签:rpo   zh-cn   delegate   his   sys   md5   eve   lazy   send   

示例

以下一个简单的异步事件TCP客户端实现

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;

namespace Leestar54
{
    /// <summary>
    /// 自定义回调事件参数
    /// </summary>
    /// <typeparam name="T">泛型类返回</typeparam>
    public class TEventArgs<T> : EventArgs
    {
        public T Result { get; private set; }
        public TEventArgs(T obj)
        {
            this.Result = obj;
        }
    }

    class MyTcpClient
    {
        private string md5id;
        Thread readThread;
        Thread heartbeatThread;
        TcpClient tcpClient;
        NetworkStream ns;
        //AsyncOperation会在创建他的上下文执行回调
        public AsyncOperation AsyncOperation;
        private static MyTcpClient singleton = null;
        static readonly object lazylock = new object();

        #region Event
        //回调代理中处理事件
        public event EventHandler Connected;
        public event EventHandler<TEventArgs<JObject>> Receive;
        public event EventHandler<TEventArgs<Exception>> Error;

        //AsyncOperation回调代理
        private SendOrPostCallback OnConnectedDelegate;
        private SendOrPostCallback OnReceiveDelegate;
        private SendOrPostCallback OnErrorDelegate;

        private void OnConnected(object obj)
        {
            Connected?.Invoke(this, EventArgs.Empty);
        }

        private void OnReceive(object obj)
        {
            Receive?.Invoke(this, new TEventArgs<JObject>((JObject)obj));
        }

        private void OnError(object obj)
        {
            Error?.Invoke(this, new TEventArgs<Exception>((Exception)obj));
        }

        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        MyTcpClient()
        {
            OnConnectedDelegate = new SendOrPostCallback(OnConnected);
            OnReceiveDelegate = new SendOrPostCallback(OnReceive);
            OnErrorDelegate = new SendOrPostCallback(OnError);
        }

        /// <summary>
        /// 单例模式
        /// </summary>
        /// <returns></returns>
        public static MyTcpClient getInstance()
        {
            if (singleton == null)
            {
                lock (lazylock)
                {
                    if (singleton == null)
                    {
                        singleton = new MyTcpClient();
                    }
                }
            }
            return singleton;
        }

        //当前客户端唯一id
        public string Md5id
        {
            get
            {
                return md5id;
            }

            set
            {
                md5id = value;
            }
        }

        /// <summary>
        /// 连接服务器
        /// </summary>
        public void Connect()
        {

            try
            {
                tcpClient = new TcpClient("119.23.154.150", 9501);
                if (tcpClient.Connected)
                {
                    ns = tcpClient.GetStream();
                    //开启两个线程长连接,一个读取,一个心跳
                    readThread = new Thread(Read);
                    readThread.IsBackground = true;
                    readThread.Start();
                    heartbeatThread = new Thread(HeartBeat);
                    heartbeatThread.IsBackground = true;
                    heartbeatThread.Start();
                    System.Diagnostics.Debug.WriteLine("服务器连接成功");
                    this.SendMsg(JObject.FromObject(new
                    {
                        cmd = "connect"
                    }));
                }
            }
            catch (Exception e)
            {
                this.AsyncOperation.Post(OnErrorDelegate, e);
                Thread.Sleep(5000);
                ReConnect();
            }
        }
        /// <summary>
        /// 读取接收到的数据
        /// </summary>
        private void Read()
        {
            try
            {
                //休眠2秒让窗口初始化
                Thread.Sleep(2000);
                Byte[] readBuffer = new Byte[1024];
                while (true)
                {
                    int alen = tcpClient.Available;
                    if (alen > 0)
                    {
                        Int32 bytes = ns.Read(readBuffer, 0, alen);

                        string responseData = System.Text.Encoding.UTF8.GetString(readBuffer, 0, bytes);
                        //为了避免粘包现象,以\r\n作为分割符
                        string[] arr = responseData.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                        foreach (var item in arr)
                        {
                            if (item != string.Empty)
                            {
                                System.Diagnostics.Debug.WriteLine("接受到消息" + item);
                                JObject jobj = JObject.Parse(item);
                                this.AsyncOperation.Post(OnReceiveDelegate, jobj);
                            }
                        }
                    }
                    Thread.Sleep(500);
                }
            }
            catch (Exception e)
            {
                this.AsyncOperation.Post(OnErrorDelegate, e);
            }
        }

        /// <summary>
        /// 心跳线程
        /// </summary>
        private void HeartBeat()
        {
            try
            {
                while (true)
                {
                    Thread.Sleep(8000);
                    byte[] wb = System.Text.Encoding.UTF8.GetBytes("+h");
                    ns.Write(wb, 0, wb.Length);
                }
            }
            catch (Exception e)
            {
                this.AsyncOperation.Post(OnErrorDelegate, e);
                Thread.Sleep(5000);
                ReConnect();
            }
        }

        /// <summary>
        /// 心跳失败,则网络异常,重新连接
        /// </summary>
        public void ReConnect()
        {
            if (readThread != null)
            {
                readThread.Abort();
            }

            Connect();
        }


        public void SendMsg(string msg)
        {
            byte[] wb = System.Text.Encoding.UTF8.GetBytes(msg);
            ns.Write(wb, 0, wb.Length);
        }

        public void SendMsg(JObject json)
        {
            SendMsg(json.ToString(Formatting.None));
        }
    }
}

使用方法

MyTcpClient client = MyTcpClient.getInstance();
//保证回调函数是在创建他的上下文执行(一般是UI线程)
client.AsyncOperation = AsyncOperationManager.CreateOperation(null);
client.Error += Client_Error; ;
client.Receive += Client_Receive; ;
client.Connected += Client_Connected;
client.Connect();

参考

http://www.cnblogs.com/kex1n/p/6502002.html
https://www.codeproject.com/Articles/14265/The-NET-Framework-s-New-SynchronizationContext-Cla
http://www.cnblogs.com/leestar54/p/4591792.html
https://msdn.microsoft.com/zh-cn/library/vs/alm/system.componentmodel.asyncoperationmanager.createoperation(v=vs.85)

附件列表

     

    C# TCPClient开发手记

    标签:rpo   zh-cn   delegate   his   sys   md5   eve   lazy   send   

    原文地址:http://www.cnblogs.com/leestar54/p/7768159.html

    (0)
    (0)
       
    举报
    评论 一句话评论(0
    登录后才能评论!
    © 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
    迷上了代码!