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 ...
随机推荐
- 如何快速获取官网帮助信息 (附 11g pdf 文档)
http://docs.oracle.com/en/ 11g Release 2 (11.2) 搜索时指定网站 site:docs.oracle.com create table site:docs. ...
- awk基础05-自定义函数和脚本
在之前文章中,我们都是在命令行中写一些简短的awk命令,而awk做为一门解释型语言,一样是支持脚本运行的. 基本语法 #!/bin/awk -f # 注释 awk 脚本体 #!:同shell, ...
- HRBUST1311 火影忍者之~忍者村 2017-03-06 16:06 106人阅读 评论(0) 收藏
火影忍者之-忍者村 忍者村是忍者聚居的村子,相等于国家的军事力量.绝大部分村民都是忍者,有一些忍者会在村内开设书店.餐厅等,不过大部分忍者都是为村子执行任务的忍者,以赚取酬劳,并于战时为国家出战. ...
- Modelsim设置数据以模拟波形显示
选中希望以模拟波形显示的信号,右击选择format—>Analog(automatic) 如果你的数据是用无符号数表示一个完整的波形的,那么可能显示出来的波形样子是下面的样子,不过不要紧,这是因 ...
- ctx.header
ctx.headers 获取所有的 header 信息,等同于 ctx.header. session session的中文翻译是“会话”,当用户打开某个web应用时,便与web服务器产生一次sess ...
- 4、Docker的安装
docker官方安装文档 Mac上安装Docker Install Docker for Mac | Docker Documentation Windows安装Docker Instal ...
- 咏南中间件修正了一处BUG,调用中间件插件会报:非法访问
咏南中间件修正了一处BUG,调用中间件插件会报:非法访问将以下方法修改成如下的代码即可function TServerMethods1.GetSvrData(const accountNo, defi ...
- Open XML操作Excel导入数据
项目中发现使用OleDb(using System.Data.OleDb)相关对象处理Excel导入功能,不是很稳定经常出问题,需要把这个问题解决掉.项目组提出使用OpenXML来处理Excel的导入 ...
- Ubuntu 16.04.2 LTS 安装 jdk1.6 和 tomcat6 (二)
上一篇记录和分享了jdk1.6 在Ubuntu 16.04.2 环境下的安装配置,本文开始安装和配置tomcat 6 2 安装tomcat http://tomcat.apache.org ...
- 用MVC5+EF6+WebApi 做一个小功能(三) 项目搭建
一般一个项目开始之前都会有启动会,需求交底等等,其中会有一个环节,大讲特讲项目的意义,然后取一个高大上的项目名字,咱这是一个小功能谈不上项目,但是名字不能太小气了.好吧,就叫Trump吧.没有任何含义 ...