zoukankan      html  css  js  c++  java
  • C# Socket tcp 发送数据大小问题

      TCP/IP是可靠性传输协议,它能保证数据能按顺序的方式到达目的地.看到以上描述在写TCP/IP应用的时候似乎就可以放心了,只要程序不出意外就数据输传就是正确.但最近在做一个文件传输工作的时候确得到的结果并不是这样,发现网络环境和一次发送数据大会影响整个输传结果.以下是这两晚的测试情况

    测试内容描述:

              每个文件块信息包大概是120k左右

              采用异步5连接输传,双方的Socket.SendBufferSize和Socket.ReceiveBufferSize都设置为64K

              测试服务器分别有:

                       局域网:ServerA

                       在美国机房:ServerB 延时高,Ping有时会超时

              测试client一台,通过ADSL上网.

    以下是Client从Sever下载文件的情况:

    • 服务器8K SendBuffer,客户端是8K ReceiveBuffer

    从ServerA下载文件,分别下载多个文件几M到几百M不等,下载后文件正确.

    从ServerB下载文件,分别下载多个文件,几M或更小的文件有部分正确,大文件基本都是错误.两端记录的发送的字节数和接收的字节相等,符合文件大小,程序也没有跟踪到数据接收异常导致的协议分解错误.

    • 服务器4K SendBuffer,客户端8K ReceiveBuffer

    从ServerA下载文件,分别下载多个文件几M到几百M不等,下载后文件正确.

    从ServerB下载文件,分别下载多个文件,文件的正确率比较高,不过还是大文件相对错误比较多.当开启迅雷下载后情况就开始变坏,大部分接收到的文件都出问题,两端记录的发送的字节数和接收的字节相等,符合文件大小,程序也没有跟踪到数据接收异常导致的协议分解错误

    • 服务器2K SendBuffer,客户端8K ReceiveBuffer

    从ServerA下载文件,分别下载多个文件几M到几百M不等,下载后文件正确.

    从ServerB下载文件,分别下载多个文件,下载结果没有发现错误文件.当开启迅雷下载后还是有个别文件错误,两端记录的发送的字节数和接收的字节相等,符合文件大小,程序也没有跟踪到数据接收异常导致的协议分解错误

    • 服务器1K SendBuffer,客户端8K ReceiveBuffer 

    从ServerA下载文件,分别下载多个文件几M到几百M不等,下载后文件正确.

    从ServerB下载文件,分别下载多个文件,下载结果没有发现错误文件.当开启迅雷下载后没有发现文件错误.

    测试文件发送到Server和下载的情况基本差不多,这说明了在网络不好的情况处理发送大数据包似首容易产生错误,但看TCP/IP协议讲解这情况似乎不存在,因为当一个发送数据超过某个值的时候,TCP会划分块进行传输并保证其顺序.但网络不好的情况测试结果接收的数据有错误,但处理的数据大小是正确的,也并没影响整个协议的分解.由于对CP/IP协议、低层和路由处理的不了解,暂没找到具体原因。。。不排除程序存在还没发现的错误,打算给发送的文件数据加上校验再测试一下看情况

    补充一下

    以上测试只修改了一个属性

    TcpUtils.SendBufferLength = 1K,2K,4K,8K

    但只有1K的测试结果奇怪地没出现文件错误,其了几中均出现仅仅是对ServerB,对ServerA来说没有出现,2K,4K也只是开启迅雷的时候错误情况多.

    发布bee网络文件管理工具

    Bee是基于c#编写免费的网络文件管理工具,分别有服务端和客户端;主要功能包括:多线程文件上传、下载、续传,在线压缩、解压等功能,还具备同时对多个服务进行操作.

    下载

    文件上传下载流程设计

        最近在写一个文件上传下载的服务端和客户端,在开发之前把交互流程大概设计了一下顺便分享出来,流程主要包括验证,交口端口验证,文件上和文件下载等功能.之于文件删除,在线压缩和解压等流程相对简单所以就不列出来了.

    登陆和交互端验证

    其实很多网络通讯应用中登陆和数据交互都是分开端口服务的,这样就存在一个数据交互连接合法性的验证,以下是针对这验证的流程设计.

    上传文件流程

    上传文件主要的工作是服务验证用户是否有权,客户端提交上传文件信息,然后把文件分割成N个小数据包,通过多线程+队列的方式实现多线程上传.把分割信息存到文件或数据库我们就能实现续传了

    文件下载

    文件下载和上传原理差不多,先从服务器检测文件获取文件信息.客户端根据文件信息分割信息块存放到队列中(多队列+线程实现多线程下载方式),文件分割信息存放文件或数据后同样也可以实现续传.

    到这里流程设计就结束,顺便共享一个文件分割类

    延时拼包机制让c# socket实现海量数据包广播吞吐

        之前已经简单的测试了c# socket的数据吞吐处理能力,结果虽然比较理想;但以这样的数据包处理量在某些场景下是远远不够用的,在某些应用场景中每秒要处理的数据包不是1,2W个可能几W,上10W或更多的数据包吞吐。在一个游戏场景中同场景存在100用户,每个用户的变更都会通知其他199的用户,如果每个用户平均每秒变更3次,那服务端每秒接收转发的数据包就是100x100x3=3w个。如果是200个用户同场景,那所每秒所面对的处理包会是200x200x3=12W个,想c# socket提供这么密集的IO处理是不太可能的事情,即使是可以那也要很不错的硬件支撑。

        从软件上去解决这问题那只能选择减少IO操作,之前的测试表明SendAsync这相的IO操作是非常损耗资源。既然问题已经知道发生在什么地方,我们可以采用减少SendAsync又不影响交互性来达到这一点。大家知道网络访问存在一个延时的系数,通过在可接受的延时区间可以把发送的A的N个数据包打包到一个buffer里,然后进行一次SendAsync操作,原本在这一时间段时有100个消息包发给A,那可以打包成一个这样SendAsync的操作就可以从原来的100次变成一次;那些这节省是相当可观的,当然这个设计尽可能根据当前调度情况来确定,调度空闲的情况下不合拼,调度存在压力的时候进行一个合拼处理。

       以下是针对这个设计的测试结果:

    测试硬件:

    server:Core2 4300 1.8G 2G win2003

    client1:Core i7 Q740 1.7G 4G win764

    client2:P4 2.4G 1G WIN2003

    测试逻辑:

    每个client程序开启50个连接,每个连接秒产生3次座标变化告诉服务端,由服务端专发给其他client.

    定期为每个client发送ping包,检测服务器处理和回发的延时时间。

    数据结构:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    public class ChangePostion:IMessage
        {
            public int X
            {
                get;
                set;
            }
            public int Y
            {
                get;
                set;
            }
            public string ID
            {
                get;
                set;
            }
     
            public void Save(BufferWriter writer)
            {
                writer.Write(X);
                writer.Write(Y);
                writer.WriteBlock(ID);
            }
     
            public void Load(BufferReader reader)
            {
                X = reader.ReadInt32();
                Y = reader.ReadInt32();
                ID = reader.ReadBlock();
            }
            private static Random ran = new Random();
            public static ChangePostion GetPoint()
            {
                ChangePostion cp = new ChangePostion();
                cp.X = ran.Next(1, 399);
                cp.Y = ran.Next(1, 399);
                return cp;
            }
        }
        public class Ping : IMessage
        {
            public string ID
            {
                get;
                set;
            }
            public DateTime Ticks
            {
                get;
                set;
            }
     
            public void Save(BufferWriter writer)
            {
                writer.WriteBlock(ID);
                 
            }
     
            public void Load(BufferReader reader)
            {
                ID = reader.ReadBlock();
            }
        }

    100人同场景测试

     服务端程序情况:

     client情况

    测试情况来看每个client每秒接收1.6w个数据包,两个client接收大概3.2W个数据包,服务端的下行带宽是2MB/秒,每秒处理3.2W对象写入缓冲发送。

    200人同场景测试

     服务器端情况

    客户端情况

    测试情况来看每个client每秒接收3.2w个数据包,4个client接收大概13W个数据包,服务端的下行带宽是8MB/秒,每秒处理13W对象写入缓冲发送

    注意

    当使用了拼包的时候就要考虑一下Socket.NoDelay是否需要开启,还有client的ReceiveBufferSize是否需要加大,在测试过程中当存在大量数据包接收的时候有个别client连接接收到的数据不正常,之于这个问题是.net的内置缓冲问题还是程序设计上的缺陷还在追查中(查明原因后会编写文章讲述问题情况)。

    下载测试程序

    BeetleTest20111127.rar (935.91 kb)

    跑测试程序最好把client分布在不同机器上

     通过上面的测试可以让想用C# Socket做应用的朋友更进一步了解它的处理能力到底怎样。对于想要源码的朋友就不需要问了,对于些问题的分析可以访问:www.henryfan.net

    10 2011 档案

    网络数据处理缓冲区和缓冲池实现
    摘要: 在编写网络应用的时候数据缓冲区是应该比较常用的方式,主要用构建一个内存区用于存储发送的数据和接收的数据;为了更好的利用已有数据缓冲区所以构造一个缓冲池来存放相关数据方便不同连接更好地利用缓冲区,节省不停的构造新的缓冲区所带的损耗问题。缓冲区其实构造一个缓冲区非常简单,根据需分本相关大小的byte数组即可;既然是用于存放数据那就自然要实现读和写方法,看一下具体实现public class DataBuffer : IDisposable { public byte[] Data; private int mLength; private int...阅读全文

    posted @ 2011-10-31 10:06 smark 阅读(1654) | 评论 (2) 编辑

    缺省数据库描述对象的数据库访问模式
    摘要: 当我们去操作数据库的时候都必须构建一个组件的环境对象,似乎这种传统的操作模式这样做是必须的也没有什么问题(就如同你在传统ADO.NET方式下操作数据打开连接一下).但细想一下会发现一个问题,很多时候的应用只是针对一个数据库;既然很多时候只针对一个数据库为什么组件在设计时不提供一个缺省的操作模式呢?让数据操作上节省了构造组件访问对象这一步(当然也应该提供,因为总要面对同时操作多个数据库的时候). 其实设计这种访问模式并不难,只需要在设计的时候提供一些缺省参数方法即可?12345678910111213141516public IList<T> List<T>(Region阅读全文

    posted @ 2011-10-19 11:02 smark 阅读(250) | 评论 (0) 编辑

    Smark.Data 开源数据访问组简介
    摘要: Smark.Data是一款开源轻量级的数据访问组件,它能提供极其方便高效的数据访问操作;灵活的条件操作方式和数据获取描述是现有很多数据库访问组件所不具备.以下对组件的使用进行简单的介绍.项目地址:http://smark.codeplex.com/blog:http://www.cnblogs.com/smarkhttp://henryfan.net设置访问数据类型和连接信息在操作数据库这前设置相关信息是必须的,组件可以通过以下代码设置数据库访问类型和连接信息(也可以通过配置文件进行设置).?123string dbpath = @"Data Source=..\\..\\..\\l阅读全文

    posted @ 2011-10-17 12:02 smark 阅读(1088) | 评论 (18) 编辑

    C#运算符重载实现动态SQL生成
    摘要: C#提供运算符重载功能,但这功能使用的场合并不多,相信很多C#开发人员虽然了解到有这一功能,但相信用到的比较少.为什么要自己重载运算符来生成SQL而不去用Linq?其目的也是非常简单的使用简单和灵活。先来看一下有多少运算符可以重载:+, -, *, /, %, &, |, ^, <<, >>==, !=, <, >, <=, >=看上去还是挺多的,应该能满SQL对应的需要,首先整理出一个对应关系c# SQL== =!= <>> >>= >=< <<= <=& and| o阅读全文

    posted @ 2011-10-15 10:01 smark 阅读(1096) | 评论 (13) 编辑

    C#实现一个简单的工作队列调度器
    摘要: 有些情况下需要一个调度器专门来处理一些工作,如在网络处理程序中,当接收的数据后把信息存放到队列中,尽可能的更快地处理下一接收操作.而接收的数据信息则由调试器来处理,如数据分析,数据包处理等等工作.既然调度器负责处理工作,那最好给需要处理的工作制定一个规则,方便以后灵活扩展处理.制定规则接口?12345public interface IWorkItem:IDisposable{void Execute();}其实接口制定很简单就是一个Execute方法,表示对该工作执行;那为什么还要实现IDisposable呢,目的就是为这工作提供一个释放操作描述,当此项工作完成会有一个释放行为处理相关事..阅读全文

    posted @ 2011-10-14 13:00 smark 阅读(1187) | 评论 (2) 编辑

    VsSingleFileGenerator插件创建,安装和使用
    摘要: 相信很多用过VS朋友都会发现一个问题,就是当编写一个XML或一个资源文件的时候VS会为该文件同时生成个类文件;其实我们也可以针对某种文件来实现自定义的生成效果,这种插件就是VS提供给相关文件的自定义工具功能(Custom Tools);下面将为大家介绍如何构造一个VsSingleFileGenerator插件,制作安装发布和在VS中使用.编写插件首先要知道的编写这样一个插件需要什么,其实这东西在Google一搜应该就有不少资料和相关sample,直接拿下来看下基本知道原来.编写这样一个插件所需要用到的是一个接口IVsSingleFileGenerator,对于这个接口的详细介绍可以通过MSD.阅读全文

    posted @ 2011-10-13 16:16 smark 阅读(692) | 评论 (2) 编辑

    安装和使用Smark.Data.I2MGenerator
    摘要: Smark.Data.I2MGenerator是Smark.Data组件的实体类生成工具,安装完成后会自动添加到VS插件里。通过该插件可以通过编写一个简单的接类文件就能自动生成相对应实体类文件,从而降低实体类的编写的复杂性。程序支持winxp,win2003,win7下的VS2008和VS2010(暂时只支持c#)。 下载地址:http://smark.codeplex.com/releases/view/45483#DownloadId=175073使用只需要设置相关文件的自定义工具为:i2m即可插件生成实体效果阅读全文

    posted @ 2011-10-13 11:27 smark 阅读(77) | 评论 (0) 编辑

    通过VS2010性能分析来查找代码中那些地方最损耗资源
    摘要: 在编写完成一个程序后,大家都比较关心程序的性能如何,想把程序优化得更好。很多时候凭个人直觉来优化程序是件非常不靠普的事情,即使你是一个优秀的开人员也很难准确地判断程序中那些出现问题。VS2010提供了性能分析工具就能轻松地帮我们解决这一事情。假设现在写了一个组件,很想知道组件和代码的性能情况。这个可以简单地写一个测试程序。View Code 测试程序写好后可以通过VS2010分析菜单里选择启用性能...阅读全文

    posted @ 2011-10-12 00:47 smark 阅读(3902) | 评论 (28) 编辑

    11 2011 档案

    延时拼包机制让c# socket实现海量数据包广播吞吐
    摘要: 之前已经简单的测试了c# socket的数据吞吐处理能力,结果虽然比较理想;但以这样的数据包处理量在某些场景下是远远不够用的,在某些应用场景中每秒要处理的数据包不是1,2W个可能几W,上10W或更多的数据包吞吐。在一个游戏场景中同场景存在100用户,每个用户的变更都会通知其他199的用户,如果每个用户平均每秒变更3次,那服务端每秒接收转发的数据包就是100x100x3=3w个。如果是200个用户同场景,那所每秒所面对的处理包会是200x200x3=12W个,想c# socket提供这么密集的IO处理是不太可能的事情,即使是可以那也要很不错的硬件支撑。 从软件上去解决这问题那只能选择减少I...阅读全文

    posted @ 2011-11-28 10:17 smark 阅读(1679) | 评论 (19) 编辑

    C# Socket Tcp 性能测试
    摘要: 前段时间讲述了在编写一个高性能的Socket Tcp服务要注意的细节[c#编写高性能Tcp Socket应用注意事项];按那些细节描述的方法来实现一个Socket Tcp性能到底达到一个怎样的效果呢?以下是针对相关方法实现的Socket Tcp服务进行一个测试,看一下在那种方式编写的Socket Tcp达到一个怎样的性能指标。测试环境server:Core2 4300 1.8G 2G内存 win2003client1:Core i7 Q740 1.7G 4G内存 win 764client2:P4 2.4G 1G内存 WIN2003由于I7 Q740装的是win7 系统所以没有拿来做服务器端。阅读全文

    posted @ 2011-11-21 10:01 smark 阅读(1847) | 评论 (17) 编辑

    c#编写高性能Tcp Socket应用注意事项
    摘要: 以下是在实现一个高性能Socket组件总结下来的问题,如果你只需要处理几千的并发应用那代码编写上注意一下就行了,但需要面对上万或几万的并发应用.那以下问题的总结,相信对编写这方面的应用有很大的帮助.SocketAsyncEventArgs这个对象是.net 2.0 sp1后提供的,主要用于实现高性能Socket数据发送和接收处理(对于更详细的介绍可以到MSDN上了解).该对象提供了三个方法设置相关发送和接收的缓冲区,SetBuffer(Int32, Int32),SetBuffer(Byte(), Int32, Int32),BufferList,前两者不能和后者共存(MSDN上有说明原因..阅读全文

    posted @ 2011-11-14 12:27 smark 阅读(4443) | 评论 (42) 编辑

    构造BufferWriter和BufferReader实现高效的对象序列化和反序列化
    摘要: 在之前的文章讲术了如何设计一个简单的网络缓冲区和缓冲池,在.net网络应用中有一个普遍的问题就是如何把对象写入缓冲和从缓冲中读取数据还原对象.在这里会实现一个Writer和Reader方便地把信息写入缓冲区和从缓冲区读取;先看下Writer和Reader功能.BufferWriterView Code public class BufferWriter : IDisposable { private IList<Buffer> mBuffers = new List<Buffer>(20); public IList<Buffer> Buffers ...阅读全文

    posted @ 2011-11-02 12:16 smark 阅读(1124) | 评论 (3) 编辑

  • 相关阅读:
    HTML/CSS基础教程 一
    linux鼠标闪烁问题解决
    Linux运行级别(runlevel)
    linux命令——umask
    linux命令——ulimit
    算法学习(二)——二分查找
    c++(一) :从c到c++
    shell编程(二)输入,输出和算术拓展
    shell编程(一)基础
    第二次Soring冲刺计划第一天(团队)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2337268.html
Copyright © 2011-2022 走看看