示例

以下一个简单的异步事件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);
//为了避免粘包现象,以\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简单示例的更多相关文章

  1. Linux下的C Socket编程 -- server端的简单示例

    Linux下的C Socket编程(三) server端的简单示例 经过前面的client端的学习,我们已经知道了如何创建socket,所以接下来就是去绑定他到具体的一个端口上面去. 绑定socket ...

  2. C# 构建XML(简单示例)

    C# 构建XML的简单示例: var pars = new Dictionary<string, string> { {"url","https://www. ...

  3. 根据juery CSS点击一个标签弹出一个遮罩层的简单示例

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  4. ACEXML解析XML文件——简单示例程序

    掌握了ACMXML库解析XML文件的方法后,下面来实现一个比较完整的程序. 定义基本结构 xml文件格式如下 <?xml version="1.0"?> <roo ...

  5. demo工程的清单文件及activity中api代码简单示例

    第一步注册一个账户,并创建一个应用.获取app ID与 app Key. 第二步下载sdk 第三步新建工程,修改清单文件,导入相关的sdk文件及调用相应的api搞定. 3.1 修改清单文件,主要是加入 ...

  6. spring-servlet.xml简单示例

    spring-servlet.xml简单示例 某个项目中的spring-servlet.xml 记下来以后研究用 <!-- springMVC简单配置 --> <?xml versi ...

  7. SignalR 简单示例

    一.什么是 SignalR ASP.NET SignalR is a library for ASP.NET developers that simplifies the process of add ...

  8. Web API 简单示例

    一.RESTful和Web API Representational State Transfer (REST) is a software architecture style consisting ...

  9. XML引入多scheme文件约束简单示例

    XML引入多scheme文件约束简单示例,用company.xsd和department.xsd来约束company.xml: company.xsd <?xml version="1 ...

随机推荐

  1. Android targetSdkVersion 原理

    前几天 Google 官方发布文章解析 compileSdkVersion.minSdkVersion 以及 targetSdkVersion 的含义,以及合理设置各个值的意义,原文 Picking ...

  2. ASP.Net Web API 输出缓存(转)

    出处:http://www.cnblogs.com/ajilisiwei/p/6112078.html 原文的转载地址:http://www.strathweb.com/2012/05/output- ...

  3. iOS7修改UISearchBar的Cancel按钮的颜色和文字

    两行代码搞定: [[UIBarButtonItem appearanceWhenContainedIn: [UISearchBar class], nil] setTintColor:[UIColor ...

  4. Oracle EBS Add Responsibility to User by the Responsibility reference of Other User.

    Oracle EBS 11i Add Responsibility to User by the Responsibility reference of Other User. Warning: R1 ...

  5. C#基础入门 七

    C#基础入门 七 接口 由于C#语言不支持多重继承,所以可以使用接口模拟结构的继承,通过使用interface关键字,定义一个接口. interface USB { void Read(string[ ...

  6. PG数据库错误: 检测到OA幸运飞艇源码ShareLock死锁处理

    PostgreSQL 是一个免费数据库,OA幸运飞艇源码下载,详情咨询[企娥166848365]对于处理分析型+交易型混合型系统来说确实很不错,特别是版本的升级到11.2后性能提升很多,很多运行机制跟 ...

  7. Flask数据库

    一 数据库的设置 Web应用中普遍使用的是关系模型的数据库,关系型数据库把所有的数据都存储在表中,表用来给应用的实体建模,表的列数是固定的,行数是可变的.它使用结构化的查询语言.关系型数据库的列定义了 ...

  8. C# 实用小类

    /// <summary> /// 汉字转换拼音 /// </summary> /// <param name="PinYin"></pa ...

  9. WPF 新手引导

    参考了https://www.cnblogs.com/ZXdeveloper/p/8391864.html,自己随便实现了一个,记录下,比较丑 <Window x:Class="Use ...

  10. HBase - 数据写入流程解析

    本文由  网易云发布. 作者:范欣欣 本篇文章仅限内部分享,如需转载,请联系网易获取授权. 众所周知,HBase默认适用于写多读少的应用,正是依赖于它相当出色的写入性能:一个100台RS的集群可以轻松 ...