如题。因为之前在写项目程序时,没有考虑好高并发的问题。自己写了个测试用例,经测试,发现,C# 的Socket 在高并发的异步发送、接收时。丢包问题挺严重,频率很高,如:开启Server后,连接,2000个用户之后。在用户端,高并发的对Server发送信息。(无论信息长短,都出发丢数据字节的问题)(如:通讯协议的包头长度:是:8000个字节长度,但最终只接到,7960左右的字节)请问大侠们都是否遇到过这样的问题。遇到这问题时,是怎么处理?有没有好的经验?我目前只想到,既然该次发送的信息,在接收端接收不完整时候,我就丢掉该包了。但,这样对用户体验不好。如果是一些网络应用程序中,因为用户点击某个按钮后,没反应。可能还有点多一次或更多次。

解决方案 »

  1.   

    恩,我建议你可以查一下,各种环境下socket接收和发送信息的推荐字节数。
      

  2.   


    大哥意思是,对不同的运行环境,C# 的Socket 中接收与发送都有不同?
      

  3.   

    既然你把你的程序问题赖给c#了,就没有什么好说的了。既然你认定.net不是一个经得起测试的类库,那么就放弃.net吧。
      

  4.   

    嘿.net对待这么个小小的socket,随随便便就能丢掉40个字节,然后敢发布到4.0版,微软也太大胆了。
      

  5.   

    我曾经测试过开两个局域网客户端,每个1000连接死循环发8000大小的包,从来没有出现过LZ说的症状。
    LZ最好检查一下程序是否有并发冲突。
      

  6.   

    两个客户端都是1000个线程都是死循环发包。
    测试服务器是E2160双核60%-80%的CPU利用率,由于测试网卡是100Mb的100%利用率,每秒只能验证处理1500左右的请求。
      

  7.   

    不知道你说的是TCP还是UDP,如果是TCP的话,我建议你还是检测一下,你的代码是否有Bug吧。或者你百度一下什么 是 TCP以及他有什么特点,如果会丢掉几个字节,那还叫TCP吗?
      

  8.   


    代码,不只是我一个人检查过的。其它同事也看过,我只是对,发送的字节数统计,与接收之后的字节数统计,结果就是我上面所说的情况。这个没有什么复杂的逻辑,就是一个+=的运行。1、发送方:int sendBytes = 0;在异步发送之后,(详细的代码我就不写了,以下s 是Socket类型变量,iar 是IAsyncResult类型变量)sendBytes += s.EndSend(iar);//这里是异步发送完之后,如果发送成功了,这些就可以加上发送成功的字节数。2、接收方:int receiveBytes = 0;在异步接收之后:receiveBytes += s.EndReceive(iar);这里没有什么复杂的逻辑,只是对sendBytes 与receiveBytes 的最终比较。我以前在大学也对TCP有过一定的认识。(安全,可靠,完整性,自检,丢了,复发,等等,这些我就不说了)但没想到,我在内网,测出这样的问题。我的其它同事,也不知道是这怎么回事。后来,改成,每个程序,只启动一个客户端,之后,一点事都没有。
      

  9.   

    sendBytes += s.EndSend(iar);
    receiveBytes += s.EndReceive(iar);
    这两是线程共享变量吗?如果是,加锁了吗?
      

  10.   


    这是异步操作的,不需要加锁。如果你了解异步特性就会知道。你上面所说的,你用线程,只是CPU上的一些异步,而C# 的Socket 的一些Begin系列的开始异步操作,与End系列的结束异步操作。是真正发挥各硬件的内部芯片,对任务的时间片高效分配,内部已实现排他锁。而且,基础数据类型的运行,本来就是原子操作,也不需要加锁。
      

  11.   

    你的CPU是单核的?你确认“sendBytes += ?”编译后是原子指令?
      

  12.   


    即使在单核CPU下 sendBytes += 也必须是原子操作. 理由我就不说了.
      

  13.   


    错了.
    正确的应该是:
    int i = 0;
    i += 1;实际上是:
    先从内存获取i的地址. 得到变量i的值. (这个时候并发会导致未写入)
    然后再加1然后再写回原址.你想想. 如果你不加锁,那么 产生覆盖的概率应该是多大呢.因为int+=操作异常简洁,所以在少量并发的时候你看不出来问题. 即便在大量并发的时候你也仅仅能看见微小的区别.所以,该是什么情况你了解了吗?
      

  14.   


    OK,这回解决了。InterLocked原子操作就可以了。
      

  15.   


    其实sp1234老师,一眼判断是我的程序问题。才这么直接说的。结果,果然是我的程序问题,因为没有用Interlocked来原子操作。所以即便是一些基础运算,还是要严格的加锁同步。谢谢大家~~~