zoukankan      html  css  js  c++  java
  • C# TCPClient简单示例

    示例

    以下一个简单的异步事件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("localhost", 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);
                            //为了避免粘包现象,以
    作为分割符
                            string[] arr = responseData.Split("
    ".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语言文件操作
      scrapy 提取XML文档
      汇编指令和寄存器
      C语言知识点
      sqlalchemy 的sqlite多线程设置
      Unity 打AssetBundle和加载方案
      unity 4种实现动态障碍方法
      入心诗词记
      人间问答
      生活中有哪些实用的心理学知识?
    • 原文地址:https://www.cnblogs.com/leestar54/p/7768159.html
    Copyright © 2011-2022 走看看