Tcp 数据对象传输接口对象设计
输入是一个对象inputObj,接口对象.Send(inputObj),对端接收之后解包成outputObj(与inputObj应相同),触发onPackageReceive事件
- 事件
public event DataServiceHandler onPackageReceived;//收包事件:
public event DataServiceHandler onPackageSent;//发包事件:
public event DataServiceHandler onPeerDisconnected;// 失连事件:
public event DataServiceHandler onSendingException;//发包异常事件;
public event DataServiceHandler onReceivingException;//收包异常时间;
public event DataServiceHandler onNotify;//对象通知事件(通知一些状态信息什么的)
- 成员
SetClient()//关联Tcp连接到数据对象传输接口,复位数据对象状态,开始接收线程,允许发
Reset()//复位数据对象状态,开始接收线程,允许发
Stop()//停止接收线程,禁止发
Send()//发送数据对象
public class draftClass
{
#region Structure
#endregion #region Fields
object locker;
TcpClient clientObj;
Messager messager=new Messager();
Thread recvThread;
#endregion #region Events
public delegate void DataServiceHandler(string msg,object sender);
public event DataServiceHandler onPackageReceived;
public event DataServiceHandler onPackageSent;
public event DataServiceHandler onPeerDisconnected;
public event DataServiceHandler onSendingException;
public event DataServiceHandler onReceivingException;
public event DataServiceHandler onNotify;
#endregion #region Functions
public void SetClient(TcpClient tc)
{
Stop();
clientObj = tc;
StartReceiving();
}
public void ReStart()
{
SetClient(this.clientObj);
}
public void Stop() { lock (recvThread) { recvThread.Abort(); } } /// <summary>
/// 打包msg和数据对象,并发送
/// </summary>
/// <param name="msg"></param>
/// <param name="o"></param>
public void Send(string msg, object o)
{
byte[] m = new byte[];
Encoding.UTF8.GetBytes(msg).CopyTo(m, );
byte[] data = ObjectToBytes(o);
byte[] d = new byte[m.Length + data.Length];
m.CopyTo(d, );
data.CopyTo(d, m.Length); Send(this.clientObj.GetStream(), d);
}
public void StartReceiving()
{
Thread t = new Thread(new ThreadStart(Receiving));
t.Name = "[DataService] Receiving Thread";
t.Start();
} private void Send(NetworkStream ns, byte[] d)
{
lock (this)
{
NetworkStream netStream = ns;
byte[] data = new byte[d.Length + ];
System.BitConverter.GetBytes(d.Length).CopyTo(data, );
d.CopyTo(data, ); netStream.Write(data, , data.Length);
}
}
private void Receiving()
{
{
Console.WriteLine("In Thread({0}),WaitingData", Thread.CurrentThread.ManagedThreadId);
NetworkStream ns = clientObj.GetStream();
while (IsOnline())
{
while (ns.DataAvailable)
{
#if DEBUG
DateTime start = DateTime.Now;
#endif
//收到的数据为2进制的原始数据,数据交给分发器处理函数
byte[] data = ReceiveByteArray(ns);
Distributor(data);
#if DEBUG
TimeSpan ts = DateTime.Now - start;
double r = data.Length * / (ts.TotalSeconds * * );
Console.WriteLine("ReceiveByteArray Length={0}\tDuring={1:f0}ms\tRate= {2:f3} Mbps", data.Length, ts.TotalMilliseconds, r);
#endif
}
//Thread.Sleep(3);
}
Console.WriteLine("In Thread({0}),clientObj Disconnect!", Thread.CurrentThread.ManagedThreadId); if (onPeerDisconnected != null)
onPeerDisconnected("Peer Disconnected",null);
Thread.CurrentThread.Abort();
}
}
//报文结构是自定义的2进制数据
//Part1:定长100字节,存放消息
//Part2:序列化了的数据对象
private void Distributor(byte[] data)
{
//解包
string msg = GetMsg(data);
object obj = GetObj(data); //msg过Messager.Paser()
if (messager.TryParser(msg, obj))
return; //如果Messager处理失败,触发onPackageReceived事件
if (onPackageReceived != null)
onPackageReceived("",data);
}
#region api
private string GetMsg(byte[] data) { return ""; }
private object GetObj(byte[] data) {return new object(); }
private byte[] ReceiveByteArray(NetworkStream stream)
{
try
{
int bufferlen = GetSize(stream);
byte[] resultbyte = new byte[bufferlen]; int offset = , bytesread = ;
while (offset < bufferlen)
{
bytesread = stream.Read(resultbyte, offset, bufferlen - offset);
if (bytesread == )
{
Console.WriteLine("?????A");
throw new Exception("网络异常断开,数据读取不完整。");
}
else
offset += bytesread;
}
return resultbyte;
}
catch (Exception)
{
Console.WriteLine("?????B");
throw;
}
}
private int GetSize(NetworkStream stream)
{
try
{
int bufferlen = ;
byte[] resultbyte = new byte[bufferlen]; int offset = , bytesread = ;
while (offset < bufferlen)
{
bytesread = stream.Read(resultbyte, offset, bufferlen - offset);
if (bytesread == )
throw new Exception("网络异常断开,数据读取不完整。");
else
offset += bytesread;
}
return System.BitConverter.ToInt32(resultbyte, );
}
catch (Exception)
{
throw;
}
}
private bool IsOnline()
{
TcpClient c = this.clientObj;
return !((c.Client.Poll(, SelectMode.SelectRead) && (c.Client.Available == )) || !c.Client.Connected);
}
/// <summary>
/// 将一个object对象序列化,返回一个byte[]
/// </summary>
/// <param name="obj">能序列化的对象</param>
/// <returns></returns>
///
private byte[] ObjectToBytes(object obj)
{
using (MemoryStream ms = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); return ms.GetBuffer();
}
}
/// <summary>
/// 将一个序列化后的byte[]数组还原
/// </summary>
/// <param name="Bytes"></param>
/// <returns></returns>
private object BytesToObject(byte[] Bytes)
{
using (MemoryStream ms = new MemoryStream(Bytes))
{
IFormatter formatter = new BinaryFormatter(); return formatter.Deserialize(ms);
}
}
#endregion
#endregion
}
DataService.cs
Tcp 数据对象传输接口对象设计的更多相关文章
- 网络TCp数据的传输设计(黏包处理)
//1.该片为引用别人的文章:http://www.cnblogs.com/alon/archive/2009/04/16/1437599.html 解决TCP网络传输"粘包"问题 ...
- TCP数据的传输过程(十)
建立连接后,两台主机就可以相互传输数据了.如下图所示: 上图给出了主机A分2次(分2个数据包)向主机B传递200字节的过程.首先,主机A通过1个数据包发送100个字节的数据,数据包的 Seq 号设置为 ...
- TCP数据的传输过程
建立连接后,两台主机就可以相互传输数据了.如下图所示: 上图给出了主机A分2次(分2个数据包)向主机B传递200字节的过程.首先,主机A通过1个数据包发送100个字节的数据,数据包的 Seq 号设置为 ...
- 4G DTU无线数据透明传输终端
4G DTU是基于4G网络的远程无线数据透明传输终端,是一种物联网无线数据传输设备,使用公用运营商的4G网络为用户提供无线远距离数据传输功能,使用工业级32位的高性能通信处理器和工业级无线模块,以嵌入 ...
- 前端H5中JS用FileReader对象读取blob对象二进制数据,文件传输
HTML5中的Blob对象只是二进制数据的容器,本身并不能操作二进制,故本篇将对其操作对象FileReader进行介绍. FileReader FileReader主要用于将文件内容读入内存,通过一系 ...
- Activity之间传递数据或数据包Bundle,传递对象,对象序列化,对象实现Parcelable接口
package com.gaojinhua.android.activitymsg; import android.content.Intent; import android.os.Bundle; ...
- DDD的实体、值对象、聚合根的基类和接口:设计与实现
1 前置阅读 在阅读本文章之前,你可以先阅读: 什么是DDD 2 实现值对象 值对象有两个主要特征:它们没有任何标识.它们是不可变的. 我们举个例子:小明是"浙江宁波"人,小红也是 ...
- HDFS对象存储--Ozone架构设计
前言 如今做云存储的公司非常多,举2个比較典型的AWS的S3和阿里云.他们都提供了一个叫做对象存储的服务,就是目标数据是从Object中进行读写的,然后能够通过key来获取相应的Object,就是所谓 ...
- 网络层、传输层、应用层、端口通信协议编程接口 - http,socket,tcp/ip 网络传输与通讯知识总结
引: http://coach.iteye.com/blog/2024511 什么是TCP和UDP,以及二者区别是什么? TCP的全称为传输控制协议.这种协议可以提供面向连接的.可靠的.点到点的通信. ...
随机推荐
- Key lock 的秘密
研究死锁,或者观察sp_lock,有时候最恼人的莫过于你看到下面研究成果的key lock,但是却不知道究竟是哪个page 哪个row被lock住了: Exec sp_lock: 就说上面的key ...
- 一致性哈希与java实现
一致性哈希算法是分布式系统中常用的算法.比如,一个分布式的存储系统,要将数据存储到具体的节点上,如果采用普通的hash方法,将数据映射到具体的节点上,如key%N,key是数据的key,N是机器节点数 ...
- 0301——Notification 通知
注册消息 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(方法) name:@"消息名字&q ...
- OC基础 点语法的使用
OC基础 点语法的使用 1.创建一个Student类继承于NSObject,Student.h文件 #import <Foundation/Foundation.h> @interface ...
- OD学习笔记10:一个VB程序的加密和解密思路
前边,我们的例子中既有VC++开发的程序,也有Delphi开发的程序,今天我们给大家分析一个VB程序的加密和解密思路. Virtual BASIC是由早期DOS时代的BASIC语言发展而来的可视化编程 ...
- Codeforces Round #350 (Div. 2)A,B,C,D1
A. Holidays time limit per test 1 second memory limit per test 256 megabytes input standard input ou ...
- “Win”组合键
Windows组合键功能: 单独按下显示或隐藏 [开始] 功能表. +Break 显示 [系统内容] 对话方块. +D 显示桌面. +M 最小化所有的视窗. +Shift+M 还原最小化的视窗. +E ...
- 【7】用Laravel5.1开发一个简单的博客系统
声明: 本教程参考Jeffrey way 在laracasts.com上的视频教程,感谢Jeffrey way为大家带来的精彩教程,本教程如有侵权,请及时告知,联系邮箱wanglv93@gmail.c ...
- 关于TP的RBAC的使用
如果你是一个TP的重度使用者的话,请自动略过笔者以下文字 权限管理我在成为一个开发者1年半内,接触过2种,一种就是数学方式 比如我们文件夹权限的755这种权限管理的方式,这种二进制的权限管理的方式 无 ...
- php中的MVC模式运用
[size=5][color=Red]php中的MVC模式运用[/color][/size] 首先我来举个例子: 一个简单的文章显示系统 简单期间,我们假定这个文章系统是只读的,也就是说这个例子将不涉 ...