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);
//为了避免粘包现象,以\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();
参考
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简单示例的更多相关文章
- Linux下的C Socket编程 -- server端的简单示例
Linux下的C Socket编程(三) server端的简单示例 经过前面的client端的学习,我们已经知道了如何创建socket,所以接下来就是去绑定他到具体的一个端口上面去. 绑定socket ...
- C# 构建XML(简单示例)
C# 构建XML的简单示例: var pars = new Dictionary<string, string> { {"url","https://www. ...
- 根据juery CSS点击一个标签弹出一个遮罩层的简单示例
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- ACEXML解析XML文件——简单示例程序
掌握了ACMXML库解析XML文件的方法后,下面来实现一个比较完整的程序. 定义基本结构 xml文件格式如下 <?xml version="1.0"?> <roo ...
- demo工程的清单文件及activity中api代码简单示例
第一步注册一个账户,并创建一个应用.获取app ID与 app Key. 第二步下载sdk 第三步新建工程,修改清单文件,导入相关的sdk文件及调用相应的api搞定. 3.1 修改清单文件,主要是加入 ...
- spring-servlet.xml简单示例
spring-servlet.xml简单示例 某个项目中的spring-servlet.xml 记下来以后研究用 <!-- springMVC简单配置 --> <?xml versi ...
- SignalR 简单示例
一.什么是 SignalR ASP.NET SignalR is a library for ASP.NET developers that simplifies the process of add ...
- Web API 简单示例
一.RESTful和Web API Representational State Transfer (REST) is a software architecture style consisting ...
- XML引入多scheme文件约束简单示例
XML引入多scheme文件约束简单示例,用company.xsd和department.xsd来约束company.xml: company.xsd <?xml version="1 ...
随机推荐
- Android targetSdkVersion 原理
前几天 Google 官方发布文章解析 compileSdkVersion.minSdkVersion 以及 targetSdkVersion 的含义,以及合理设置各个值的意义,原文 Picking ...
- ASP.Net Web API 输出缓存(转)
出处:http://www.cnblogs.com/ajilisiwei/p/6112078.html 原文的转载地址:http://www.strathweb.com/2012/05/output- ...
- iOS7修改UISearchBar的Cancel按钮的颜色和文字
两行代码搞定: [[UIBarButtonItem appearanceWhenContainedIn: [UISearchBar class], nil] setTintColor:[UIColor ...
- 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 ...
- C#基础入门 七
C#基础入门 七 接口 由于C#语言不支持多重继承,所以可以使用接口模拟结构的继承,通过使用interface关键字,定义一个接口. interface USB { void Read(string[ ...
- PG数据库错误: 检测到OA幸运飞艇源码ShareLock死锁处理
PostgreSQL 是一个免费数据库,OA幸运飞艇源码下载,详情咨询[企娥166848365]对于处理分析型+交易型混合型系统来说确实很不错,特别是版本的升级到11.2后性能提升很多,很多运行机制跟 ...
- Flask数据库
一 数据库的设置 Web应用中普遍使用的是关系模型的数据库,关系型数据库把所有的数据都存储在表中,表用来给应用的实体建模,表的列数是固定的,行数是可变的.它使用结构化的查询语言.关系型数据库的列定义了 ...
- C# 实用小类
/// <summary> /// 汉字转换拼音 /// </summary> /// <param name="PinYin"></pa ...
- WPF 新手引导
参考了https://www.cnblogs.com/ZXdeveloper/p/8391864.html,自己随便实现了一个,记录下,比较丑 <Window x:Class="Use ...
- HBase - 数据写入流程解析
本文由 网易云发布. 作者:范欣欣 本篇文章仅限内部分享,如需转载,请联系网易获取授权. 众所周知,HBase默认适用于写多读少的应用,正是依赖于它相当出色的写入性能:一个100台RS的集群可以轻松 ...