fdssdfa

导航

最新的.Net TcpSocket修正,加入边界的处理.



/Files/liuzhiwei/Liuzhiweisoft.Netanddemo.rar
    (含原码和列子)

这次对原码做了更多的解释.

/*
 * 我简单介绍一下这次的改动:
 * 很多朋友问到搞不明白这个组件怎么工作的,TcpSocketEventArgs是干什么的,这个组件本身并不复杂,
 * 把TcpSocketEventArgs看成是一个Socket就明白了,其实就是对Socket的一个封装类。
 * 还有问到组件里激发事件的地方是在线程里的,为什么我们写在事件里的代码可以直接对UI进行操作。
 * 其实在组件构造的时候我们就取得UI线程的上下文SynchronizationContext.Current,
 * 在构造TcpSocketEventArgs的时候传递了这个SynchronizationContext,最终激发事件是发回UI线程来执行的。
 * 我们写在事件里的收发代码其实最终都是到UI线程去执行的。
 * 以前这样做的原因主要是考虑到方便,因为我们可以直接对UI操作,但是也引出了一个很严重的问题,同时
 * 发送5,6个文件就会觉得很卡,UI控制不顺畅。甚至都移动不了窗体。就是因为收发数据的代码全部都是在
 * UI线程里完成的,UI线程没有得到足够时间来干他自己的事情,最终造成整个UI迟钝,
 * UI 线程不应该用于执行任何耗时较长的操作,任何耗时超过 30ms 的操作都要考虑从 UI 线程中移除。
 * 为了不丢失方便,添加了一个新函数,UpdateUi("labelprogress");
 * 我们调用这个函数的时候需要传递一个标记符,每当调用这个函数就会触发UpdateUi事件,
 * 这个UpdateUi事件是执行在UI线程上的,可以对UI直接操作。比如下
 *   private void tcpClient1_UpdateUi(object sender, string tag, Liuzhiweisoft.Net.TcpSocketEventArgs e)
 *    {
 *           switch (tag)
 *              {
 *                    case "labelprogress":
 *                   e.label.Text = e.FileSeek.ToString() + "B / " + e.FileSize.ToString() + "B";
 *                   e.progressbar.Value = (int)e.FileSeek;
 *                  break;
 *              }
 *    }
 * 依然不麻烦。我们只是把所有的和UI相关的操作全部在这个事件里处理。
 * 虽然现在我们只有一个事件去UI线程激发,但是依然还是要注意,不要让UI线程执行毫时操作。
 *
 * 第二个改动的地方就是添加了对边界的处理,但是依然保持以前无边界处理,
 * 现在SEND,RECEIVE函数有3个重载了,新添加的两个:
 * public int Receive(out UInt16 socketTag,out byte[] buffer)
 * public int Send(UInt16 dataTag,Byte[] buffer)
 * 我们用这两个函数进行收发就要方便很多了,我们不用去考虑很多让人郁闷的问题了。
 *
 * 简单介绍一下对边界做的处理。
 * 公式:数据大小+标记符+数据
 * 数据大小=4字节,有符号Int32,相当于我们可以描述一个数据包的数据大小为2,147,483,647,完全足够。
 * 标记符=2字节,无符号UInt16,相当于我们可以描述的标记大小为0-----65535,完全足够。
 * 数据=我们实际发送的数据。
 *
 * 数据大小描述的其实就是数据的大小,听起来有一些幽默,呵呵,事实就是如此。
 * 标记符描述的其实就是代表这个数据到底是属于什么数据,比如1代表是一个文件基础信息数据。
 *
 * 当我们调用public int Send(UInt16 dataTag,Byte[] buffer)的时候,
 * 第一个参数是用来描述数据类型的,第二个参数是要发送的buffer。
 * 这个函数里会用上面的公式组合后才发送。
 *
 * 当我们调用public int Receive(out UInt16 socketTag,out byte[] buffer)的时候,
 * 第一个参数是用来接收数据类型的,第二个参数是要接收到的buffer.
 * 这个函数里会用上面的公式进行分解。
 * 然后干的事情总结起来就是一句话,确保你发送的多少,在这里就完整的收多少。
 * 比如Send发送了165300字节,调用Receive方法会一直保持阻止,直到完整收到165300字节后才返回。
 * 如果你不想处理麻烦的收发问题,一定要去调这两个新的重载Send,Receive函数,否则是不做任何处理的。
 *
 * 还有其他许多等等问题有待解决。比如组件不确定使用者要用到一些什么类型,需要一些什么成员用于
 * 收发数据,如果我们在组件里放一个HashTable等容器来描述各种不同类型的成员,收发代码写起来会非常
 * 的烦琐。依然还是不能很好的实现组件和收发代码的完全分离。
 *
 * 好了,就到这里吧,我还是先放上来吧,欢迎大家共同探讨。
 *
 *
 * 
 *
 *
 */

posted on 2007-09-17 14:17  dfsafdas  阅读(3993)  评论(8编辑  收藏  举报