输入是一个对象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 数据对象传输接口对象设计的更多相关文章

  1. 网络TCp数据的传输设计(黏包处理)

    //1.该片为引用别人的文章:http://www.cnblogs.com/alon/archive/2009/04/16/1437599.html 解决TCP网络传输"粘包"问题 ...

  2. TCP数据的传输过程(十)

    建立连接后,两台主机就可以相互传输数据了.如下图所示: 上图给出了主机A分2次(分2个数据包)向主机B传递200字节的过程.首先,主机A通过1个数据包发送100个字节的数据,数据包的 Seq 号设置为 ...

  3. TCP数据的传输过程

    建立连接后,两台主机就可以相互传输数据了.如下图所示: 上图给出了主机A分2次(分2个数据包)向主机B传递200字节的过程.首先,主机A通过1个数据包发送100个字节的数据,数据包的 Seq 号设置为 ...

  4. 4G DTU无线数据透明传输终端

    4G DTU是基于4G网络的远程无线数据透明传输终端,是一种物联网无线数据传输设备,使用公用运营商的4G网络为用户提供无线远距离数据传输功能,使用工业级32位的高性能通信处理器和工业级无线模块,以嵌入 ...

  5. 前端H5中JS用FileReader对象读取blob对象二进制数据,文件传输

    HTML5中的Blob对象只是二进制数据的容器,本身并不能操作二进制,故本篇将对其操作对象FileReader进行介绍. FileReader FileReader主要用于将文件内容读入内存,通过一系 ...

  6. Activity之间传递数据或数据包Bundle,传递对象,对象序列化,对象实现Parcelable接口

    package com.gaojinhua.android.activitymsg; import android.content.Intent; import android.os.Bundle; ...

  7. DDD的实体、值对象、聚合根的基类和接口:设计与实现

    1 前置阅读 在阅读本文章之前,你可以先阅读: 什么是DDD 2 实现值对象 值对象有两个主要特征:它们没有任何标识.它们是不可变的. 我们举个例子:小明是"浙江宁波"人,小红也是 ...

  8. HDFS对象存储--Ozone架构设计

    前言 如今做云存储的公司非常多,举2个比較典型的AWS的S3和阿里云.他们都提供了一个叫做对象存储的服务,就是目标数据是从Object中进行读写的,然后能够通过key来获取相应的Object,就是所谓 ...

  9. 网络层、传输层、应用层、端口通信协议编程接口 - http,socket,tcp/ip 网络传输与通讯知识总结

    引: http://coach.iteye.com/blog/2024511 什么是TCP和UDP,以及二者区别是什么? TCP的全称为传输控制协议.这种协议可以提供面向连接的.可靠的.点到点的通信. ...

随机推荐

  1. IO中手机旋转事件的传递

    UIApplication -> delegate -> widnow -> rootViewController

  2. HTTP 503 错误 – 服务不可用 (Service unavailable)

    介绍 因暂时超载或临时维护,您的 Web 服务器目前无法处理 HTTP 请求. 其含义是, 这是一个暂时情况,会有一些延误, 过 后将会得到缓解. 有些服务器在这种情况下也许干脆拒绝套接字(socke ...

  3. js判断浏览器类型以及版本

    你知道世界上有多少种浏览器吗?除了我们熟知的IE, Firefox, Opera, Safari四大浏览器之外,世界上还有近百种浏览器. 几天前,浏览器家族有刚诞生了一位小王子,就是Google推出的 ...

  4. (转)一小时搞定DIV+CSS布局-固定页面开度布局

    本文讲解使用DIV+CSS布局最基本的内容,读完本文你讲会使用DIV+CSS进行简单的页面布局. 转载请标明:http://www.kwstu.com/ArticleView/divcss_20139 ...

  5. c#按键Up和Down对Textbox的内容加1减1

    private void textBox_proc1value_KeyDown(object sender, KeyEventArgs e) { Keys key = e.KeyCode; if (e ...

  6. android 开发中判断网络是否连接的代码

    在android的开发中,尤其是与访问网络有关的开发,都要判断一下手机是否连接上了网络,下面是一个判断是否连接网络的嗲吗片段: package cn.com.karl.util; import com ...

  7. java 操作POI参考文章

    http://blog.csdn.net/softwave/article/details/38071825 http://www.cnblogs.com/ivan0626/archive/2013/ ...

  8. python学习(四)五数连珠

    中午有段时间,模仿<五子连珠>写了一段代码,运行截图如下: import random # for random.randrange() import os # for input() b ...

  9. Halloween party

    https://www.hackerrank.com/challenges/halloween-party def main(): t = int(raw_input()) for _ in rang ...

  10. Android Support Library package简介

    转自http://my.oschina.net/chengliqun/blog/148451 N久未做android了,以前做的时候,2.2才刚出来,现在android都更新到了4.3了,而从前一段时 ...