经过一年时间的沉淀 再次回首 TCP Socket服务器编程 (转)

------------------

前言

------------------

开发了这么多年,发现最困难的程序开发就是通讯系统。

 

其他大部分系统,例如CRM/CMS/权限框架/MIS之类的,无论怎么复杂,基本上都能够本地代码本地调试,性能也不太重要。(也许这个就是.net的企业级开发的战略吧)

 

可是来到通讯系统,一切变得困难复杂。原因实在太多了,如:

  • 性能永远是第一位:有时候一个if判断都要考虑性能,毕竟要损耗一个CPU指令,而在通讯系统服务器,每秒钟都产生上百万级别的通讯量,这样一个if就浪费了1个毫秒了。
  • 系统环境极其恶劣:所有我们可以想象的恶意攻击、异常输入等都要考虑;
  • 网络说断就断:在socket环境下,客户端可以以各种理由断开链接,而且服务器根本不会知道,连一个流水作业的业务逻辑都无法保证正常执行,因此需要设计各种辅助的协议、架构去监督。
  • 各种网络链接问题:例如代理、防火墙等等。。。

经过了1年的跌跌撞撞,我总算收获了点有用的经验,本文先从设计角度介绍一些我在Socket编程中的经验,下一篇在放出源代码。

 

------------------

现有的Socket编程资源

------------------

1. 首选推荐开源的XMPP框架,也就是Google的Gtalk的开源版本。里面的架构写的非常漂亮。特点就是:简洁、清晰。

 

2. 其次推荐LumaQQ.net,这套框架本身写的一般般,但是腾讯的服务器非常的猛,这样必然导致客户端也要比较猛。通过学习这套框架,能够了解腾讯的IM传输协议设计,而且他们的协议是TCP/UDP结合,一举两得。

 

3. 最后就是DotMsn。这个写的实在很一般般,而且也主要针对了MSN的协议特点。是能够学习到一点点的框架知识的,不过要有所鉴别。

 

------------------

Socket的选择

------------------

在Java,到了Java5终于出现了异步编程,NIO,于是各种所谓的框架冒了出来,例如MINA, xsocket等等;而在.NET,微软一早就为我们准备好了完善的Socket模型。主要包括:同步Socket、异步Socket;我还听说了.net 3.x之后,异步的Socket内置了完成端口。综合各种模型的性能,我总结如下:

 

1. 如果是短链接,使用同步socket。例如http服务器、转接服务器等等。

 

2. 如果是长链接,使用异步socket。例如通讯系统(QQ / Fetion)、webgame等。

 

3. .net的异步socket的连接数性能在 7500/s(每秒并发7500个socket链接)。而听说完成端口在1.5w所有。但是我到目前还没有正式见过所谓的完成端口,不知道到底有多牛逼。

 

4. 我听说了java的NIO性能在5000/s所有,我们项目内部也进行了链接测试,在4000~5000比较稳定,当然如果代码调优之后,能提高一点点。

 

------------------

TCP Socket协议定义

------------------

本文从这里开始,主要介绍TCP的socket编程。

新手们(例如当初的我),第一次写socket,总是以为在发送方压入一个"Helloworld",接收方收到了这个字符串,就“精通”了Socket编程了。而实际上,这种编程根本不可能用在现实项目,因为:

 

1. socket在传输过程中,helloworld有可能被拆分了,分段到达客户端),例如 hello   +   world,一个分段就是一个包(Package),这个就是分包问题

 

2. socket在传输过成功,不同时间发送的数据包有可能被合并,同时到达了客户端,这个就是黏包问题。例如发送方发送了hello+world,而接收方可能一次就接受了helloworld.

 

3. socket会自动在每个包后面补n个 0x0 byte,分割包。具体怎么去补,这个我就没有深入了解。

 

4. 不同的数据类型转化为byte的长度是不同的,例如int转为byte是4位(int32),这样我们在制作socket协议的时候要特别小心了。具体可以使用以下代码去测试:

代码
         public   void  test()
        {
            
int  myInt  =   1 ;
            
byte [] bytes  =   new   byte [ 1024 ];
            BinaryWriter writer 
=   new  BinaryWriter( new  MemoryStream(bytes));
            writer.Write(myInt);
            writer.Write(
" j " );
            writer.Close();
        }

 

 

尽管socket环境如此恶劣,但是TCP的链接也至少保证了:

  • 包发送顺序在传输过程中是不会改变的,例如发送方发送 H E L L,那么接收方一定也是顺序收到H E L L,这个是TCP协议承诺的,因此这点成为我们解决分包、黏包问题的关键。
  • 如果发送方发送的是helloworld, 传输过程中分割成为hello+world,那么TCP保证了在hello与world之间没有其他的byte。但是不能保证helloworld和下一个命令之间没有其他的byte。

 

因此,如果我们要使用socket编程,就一定要编写自己的协议。目前业界主要采取的协议定义方式是:包头+包体长度+包体。具体如下:

 

1. 一般包头使用一个int定义,例如int = 173173173;作用是区分每一个有效的数据包,因此我们的服务器可以通过这个int去切割、合并包,组装出完整的传输协议。有人使用回车字符去分割包体,例如常见的SMTP/POP协议,这种做法在特定的协议是没有问题的,可是如果我们传输的信息内容自带了回车字符串,那么就糟糕了。所以在设计协议的时候要特别小心。

 

2. 包体长度使用一个int定义,这个长度表示包体所占的比特流长度,用于服务器正确读取并分割出包。

 

3. 包体就是自定义的一些协议内容,例如是对像序列化的内容(现有的系统已经很常见了,使用对象序列化、反序列化能够极大简化开发流程,等版本稳定后再转入手工压入byte操作)。

 

一个实际编写的例子:比如我要传输2个整型 int = 1, int = 2,那么实际传输的数据包如下:

   173173173               8                  1         2

|------包头------|----包体长度----|--------包体--------|

这个数据包就是4个整型,总长度 = 4*4  = 16。

 

说说我走的弯路:

我曾经偷懒,使用特殊结束符去分割包体,这样传输的数据包就不需要指名长度了。可是后来高人告诉我,如果使用特殊结束符去判断包,性能会损失很大,因为我们每次读取一个byte,都要做一次if判断,这个性能损失是非常严重的。所以最终还是走主流,使用以上的结构体。

 

 

------------------

Socket接收的逻辑概述

------------------

针对了我们的数据包设计+socket的传输特点,我们的接收逻辑主要是:

1. 寻找包头。这个包头就是一个int整型。但是写代码的时候要非常注意,一个int实际上占据了4个byte,而可悲的是这4个byte在传输过程中也可能被socket 分割了,因此读取判断的逻辑是:

  • 判断剩余长度是否大于4
  • 读取一个int,判断是否包头,如果是就跳出循环。
  • 如果不是包头,则倒退3个byte,回到第一点。
  • 如果读取完毕也没有找到,则有可能包头被分割了,因此当前已读信息压入接收缓存,等待下一个包到达后合并判断。

2. 读取包体长度。由于长度也是一个int,因此判断的时候也要小心,同上。

3. 读取包体,由于已知包体长度,因此读取包体就变得非常简单了,只要一直读取到长度未知,剩余的又回到第一条寻找包头。

 

这个逻辑不要小看,就这点东西忙了我1天时间。而非常奇怪的是,我发现c#写的socket,似乎没有我说的这么复杂逻辑。大家可以看看LumaQQ.net / DotMsn等,他们的socket接收代码都非常简单。我猜想:要么是.net的socket进行了优化,不会对int之类的进行分割传输;要么就是作者偷懒,随便写点代码开源糊弄一下。

 

------------------

Socket服务器参数概述

------------------

我在开篇也说了,Socket服务器的环境是非常糟糕了,最糟糕的就是客户端断线之后服务器没有收到通知。 因为socket断线这个也是个信息,也要从客户端传递到我们socket服务器。有可能网络阻塞了,导致服务器连断开的通知都没有收到。

因此,我们写socket服务器,就要面对2个环境:

1. 服务器在处理业务逻辑中的任何时候都会收到Exception, 任何时候都会因为链接中断而断开。

2. 服务器接收到的客户端请求可以是任意字符串,因此在处理业务逻辑的时候,必须对各种可能的输入都判断,防止恶意攻击。

 

针对以上几点,我们的服务器设计必须包含以下参数:

1. 客户端链接时间记录:主要判断客户端空连接情况,防止连接数被恶意占用。

2. 客户端请求频率记录:要防止客户端频繁发送请求导致服务器负荷过重。

3. 客户端错误记录:一次错误可能导致服务器产生一次exception,而这个性能损耗是非常严重的,因此要严格监控客户端的发送协议错误情况。

4. 客户端发送信息长度记录:有可能客户端恶意发送非常长的信息,导致服务器处理内存爆满,直接导致宕机。

 

5. 客户端短时间暴涨:有可能在短时间内,客户端突然发送海量数据,直接导致服务器宕机。因此我们必须有对服务器负荷进行监控,一旦发现负荷过重,直接对请求的socket返回处理失败,例如我们常见的“404”。

 

6. 服务器短时间发送信息激增:有可能在服务器内部处理逻辑中,突然产生了海量的数据需要发送,例如游戏中的“群发”;因此必须对发送进行队列缓存,然后进行合并发送,减轻socket的负荷。

 

 

------------------

后记

------------------

本文从架构设计分析了一个socket服务器的设计要点。如果您有其他见解,欢迎留言与讨论。


我们的最新动态 (Bamboo@pixysoft.net)

  • 1.基于socket的通讯架构成功集成到信息流服务器.替换第三方的即时通..[2010-6-15]

  • 2.Socket服务器第一阶段开发完成.即时通讯即将全面移植到内部即时通..[2010-6-14]

  • 3.测试驱动的自动化进程再迈进一步.使用了验证自动化.并移植refle..[2010-6-8]

  • 我们每天都在努力着!

  • 1.基于socket的通讯架构成功集成到信息流服务器.替换第三方的即时通..[2010-6-15]

  • 2.Socket服务器第一阶段开发完成.即时通讯即将全面移植到内部即时通..[2010-6-14]

  • 3.测试驱动的自动化进程再迈进一步.使用了验证自动化.并移植refle..[2010-6-8]

  • 我们每天都在努力着!

  • 1.基于socket的通讯架构成功集成到信息流服务器.替换第三方的即时通..[2010-6-15]

  • 2.Socket服务器第一阶段开发完成.即时通讯即将全面移植到内部即时通..[2010-6-14]

  • 3.测试驱动的自动化进程再迈进一步.使用了验证自动化.并移植refle..[2010-6-8]

  • 我们每天都在努力着!

  • 1.基于socket的通讯架构成功集成到信息流服务器.替换第三方的即时通..[2010-6-15]

  • 2.Socket服务器第一阶段开发完成.即时通讯即将全面移植到内部即时通..[2010-6-14]

  • 3.测试驱动的自动化进程再迈进一步.使用了验证自动化.并移植refle..[2010-6-8]

  • 我们每天都在努力着!

posted @ 2010-06-27 02:54 阅读(1961) 评论(46) 编辑 收藏

 

   回复   引用   查看     
#1楼 2010-06-27 03:55 | 木野狐(Neil Chen)       
学习一下。
   回复   引用   查看     
#2楼 2010-06-27 07:27 | 尚文雨       
深有同感,而且涉及有通信子系统的软件时,往往不同子系统是异构的技术...考虑的问题更多.推荐《用TCP/IP进行网际互联》系列书籍,还的通俗易懂,非常好,听说<<TCP/IP详解>>也不错,不过我还没有来得急看,这些对于设计有通信系统的基础很有帮助.

我做的系统服务端多是用.NET,WINDOWS的客户端多用DELPHI完成的,也有用C++的,不过较少,有些客户端还是嵌入式的.不过在开发平台这个问题上能统一我还是想尽量统一,这样设计和开发难度会降低些,最近设计一个企业的内用的系统,服务端和客户端都用.NET,用WCF通信,效果还行.



但愿能看到您此类经验更多的分享.谢谢!!

   回复   引用   查看     
#3楼 2010-06-27 08:06 | FJ. Zhou       
推荐《UNIX网络编程(卷一)》。不过里面是直接使用裸的系统Socket API,不是.NET Java之类封装过的。而Windows的WinSock API基本模仿了UNIX的API形式,有很好的借鉴价值
   回复   引用   查看     
#4楼 2010-06-27 08:48 | 聚焦       
分包和粘包,只要知道TCP是流方式传输就好理解了。
另外看文章感觉你们用的是短链接方式。这样7500/s的链接数一般都够用了。因为经验值是每个客户端断链接的话一般只会占用1%的时间来通信。这样的话理论上每个服务端应该能支持75万个客户端。
主要担心客户端瞬间发送海量数据的问题,不知道是如何解决的?我的思路是网络接收,分包解包,信息处理分为三个线程来异步实现。分包解包线程和信息处理线程优先级低于网络接收,另分包解包线程和信息处理线程循环过程中要适当的加休息时间,避免虚假宕机现象。

   回复   引用   查看     
#5楼 2010-06-27 09:18 | assiwe       
引用我曾经偷懒,使用特殊结束符去分割包体,这样传输的数据包就不需要指名长度了。可是后来高人告诉我,如果使用特殊结束符去判断包,性能会损失很大,因为我们每次读取一个byte,都要做一次if判断,这个性能损失是非常严重的。所以最终还是走主流,使用以上的结构体。

一直不明白高性能的程序传递消息都要先发送长度,原来是这么回事啊

   回复   引用   查看     
#6楼 2010-06-27 10:25 | 韦恩卑鄙 v-zhewg @waynebaby       
你用的异步io包的就是iocp windows上所有的.net异步io操作在2.0上都做了iocp的异步实现。

7500比我们以前做的实验要少

   回复   引用   查看     
#7楼 2010-06-27 10:27 | 韦恩卑鄙 v-zhewg @waynebaby       
>socket会自动在每个包后面补n个 0x0 byte,分割包。具体怎么去补,这个我就没有深入了解。
你确定这是补的? 我感觉是你传进的buffer很大 没有填满哦。。。

   回复   引用   查看     
#8楼 2010-06-27 10:29 | 螃蟹往前冲       
完成端口在.net2.0SP1就有了。对编程实现的一个最直观好处就是可以通过POOL减少异步编程中callback对象的大量创建和销毁带来的损耗。另外,在SocketAsyncEventArgs中提供了比较丰富的Buffer支持,能够和缓冲池进行有效结合,比如ArraySegment
   回复   引用   查看     
#9楼 2010-06-27 10:50 | wota       
我想问一下,既然有包长度,可不可以不要包头那个int呢?不要的话,也能好像正确解析

   回复   引用   查看     
#10楼 2010-06-27 10:53 | 非空       
对int类型的socket也会分割,看.net源码里也没有说对int的会有优化啥的,我以前做的取包头时头疼不已,比如一个包取出来了,可这个包后边还跟着下一个包的包头2个byte,其余的2个byte在下一个包里,我不得不用List维护起来,可是这样会碰到多线程的问题,不知道楼主是怎么处理这种情况的,期待楼主的socket内裤^_^
   回复   引用   查看     
#11楼 2010-06-27 10:56 | 非空       
其实到最后socket那块稳定了,时间都消耗在协议上了,一开始要设计一个好的协议就事半功倍,不知道楼主有没有协议簇、命令之类的
   回复   引用   查看     
#12楼 2010-06-27 11:01 | 韦恩卑鄙 v-zhewg @waynebaby       
@非空
我这边用一个单向链表维护所有的接收的数据,包装成一个 Queue

这里用了arraysegment 保证不会产生过多的内存碎片 可以开1mb一个的buffer 让多个node中的as 指向这个buffer的不同位置。



   回复   引用   查看     
#13楼 2010-06-27 11:01 | 韦恩卑鄙 v-zhewg @waynebaby       

   回复   引用   查看     
#14楼 2010-06-27 11:02 | 韦恩卑鄙 v-zhewg @waynebaby       

   回复   引用   查看     
#15楼 2010-06-27 11:05 | 非空       
@韦恩卑鄙 v-zhewg @waynebaby
呵呵我参考参考,回的还真快

   回复   引用   查看     
#16楼 2010-06-27 11:09 | 黄明       
看得很有收获 支持
   回复   引用   查看     
#17楼 2010-06-27 11:21 | pqmagic       
通信系统的复杂之处在于:你得先基于底层的通信协议实现自己的应用层协议,而且服务器端没有IIS之类的内建交互程序。
之前我也用socket实现了一个业务子系统。虽然前期做了很多准备工作,但还是遇到了不少问题。跟楼主一样,开始我也用特殊字符来分割网络包,后来发现在处理“分包”和“粘包”等问题上不是很好处理,就改用了传统做法。而对于分包和粘包,我采用的做法是,在服务器端和客户端都设置一适当的接收缓冲区,然后在接收线程中循环从缓冲区中读取一完整的网络包,再交给处理线程。
由于我实现的是业务类系统,客户端主要是以RPC的形式调用服务器端逻辑。想请教一下楼主,在tcp协议上实现RPC,有什么好的封包方式?我之前的做法是:协议头+消息体长度+分隔符+Action+分隔符+参数1+分隔符+参数2(其中action是要调用服务器端方法的方法名)
感觉这样做的好处是消息包比较轻量级(因为我的客户端靠GPRS通信,所以消息包越轻量越好),但跟wcf或者webservice等应用层协议相比,参数都没有类型,所以通信双方只能靠人为的约束,而不能靠程序的自动检查来实现类型转换。

   回复   引用   查看     
#18楼 2010-06-27 11:23 | ouzi       
1. 一般包头使用一个int定义,例如int = 173173173;作用是区分每一个有效的数据包,因此我们的服务器可以通过这个int去切割、合并包,组装出完整的传输协议。有人使用回车字符去分割包体,例如常见的SMTP/POP协议,这种做法在特定的协议是没有问题的,可是如果我们传输的信息内容自带了回车字符串,那么就糟糕了。所以在设计协议的时候要特别小心。

这一种不论怎么样,都是会有重复的,我们公司做的通讯系统,找的是一些不常用的字符来做的包头和包尾,如果遇到了要传输与包头一样的,就用转义来做

   回复   引用   查看     
#19楼 2010-06-27 11:27 | ouzi       
这个逻辑不要小看,就这点东西忙了我1天时间。而非常奇怪的是,我发现c#写的socket,似乎没有我说的这么复杂逻辑。大家可以看看LumaQQ.net / DotMsn等,他们的socket接收代码都非常简单。我猜想:要么是.net的socket进行了优化,不会对int之类的进行分割传输;要么就是作者偷懒,随便写点代码开源糊弄一下。

估计是偷懒,因为要做好接收端的代码,这里是非常难的一块,我们公司做的好像是找包头包尾,如果没有就丢掉,因为我们公司的这些数据,并不是非常的重要,如果丢掉了,可以再次改送(客户端再次请求),不过我个人感觉这种不好。。。


   回复   引用   查看     
#20楼 2010-06-27 11:33 | ouzi       
2. socket在传输过成功,不同时间发送的数据包有可能被合并,同时到达了客户端,这个就是黏包问题。例如发送方发送了hello+world,而接收方可能一次就接受了helloworld.

其实我认为TCP只要你的协议定好了,是没有黏包问题的,因为你有包头,长度,包尾,可以分割,其实在我认为不好处理的,应该是分包不好做,不过我们公司好像分包就像上面的回复那样,是把分的包给丢了的,唉。。。

   回复   引用   查看     
#21楼 2010-06-27 11:43 | ouzi       
不过我还是比较幸运的,基本上没有做过什么***管理系统之类的,一毕业就做起了通讯,这块,发现确实比较麻烦,不过用C#做服务器的话,我们主管说,性能还是不错的,做通讯在高层更多的感觉是做策略,比较udp的重发机制等等,在底层的话,就是2进制流的转来转去,

@pqmagic
我试着回答一下,可能没有办法做你说的那种类型检查了,做通信,就是做协议,有了协议别人不遵守,那就项目没有办法做了

   回复   引用   查看     
#22楼 2010-06-27 11:59 | wota       
@ouzi
有了包头就不用包尾了吧,tcp都做了安全传输了,只需要定义一个区分包长度的就ok了

   回复   引用   查看     
#23楼 [ 楼主]2010-06-27 12:52 |        
@ouzi

黏包问题主要发生在:

1. 客户端在很短时间突然发送n个数据包

2. 服务端处理压力很大。

这个时候socket就会把客户端瞬时间发送的包合并交给服务端处理。

你可以尝试开1000个线程,然后每个用个while(True)循环不断对服务器发信息,这样就可以看到黏包了。

实际环境中,就是网络延迟,导致黏包,如果是实验室的网络,就不会出现黏包。

   回复   引用   查看     
#24楼 2010-06-27 13:33 | tmxk2002       
此帖不错,这才是技术论坛应该有的氛围,推荐。
   回复   引用   查看     
#25楼 2010-06-27 13:56 | rgqancy       
这篇文章提出的问题好,引发的讨论好,支持。
   回复   引用   查看     
#26楼 2010-06-27 14:32 | 萨肯       
错误处理使用Exception实现的么,异常的性能不是很差么,为什么不用错误编码呢?
   回复   引用   查看     
#27楼 2010-06-27 14:57 | llzhzhbb       
我对socketasynceventargs类的bufferlist属性比较疑惑,什么情况下会用到这种方式;
另外,socketasynceventargs的接收缓冲区和发送缓冲区,在有双工同时进行的情况下,是不是有必要分成两个缓冲区。

   回复   引用   查看     
#28楼 2010-06-27 15:01 | pboyin       
虽然看不懂,但觉得你写得很好.
   回复   引用   查看     
#29楼 2010-06-27 15:09 | 亚历山大同志       
首先在4.0的框架之前,.NET一个进程只能用一个内核,所以要充分利用机器的性能必须多个进程才行,其次,.NET中使用IOCP的时候,完成事件会产生大量的线程,所以完成事件的方法必须尽快返回,所以对每一个会话建立缓冲区,将每一次完成事件接收到的数据尽快存入,尽快返回。后端的协议包处理放在后端的线程(或者进程)里处理,比如两个进程,一个负责accept socket,另外一个进程专门处理协议包,比如http协议,如果有富余的cpu内核,就开启更多的工作进程来处理数据包,这样子就可以非常的快了
   回复   引用   查看     
#30楼 2010-06-27 15:56 | WillMyPower       
写的相当不错,受益匪浅啊。
   回复   引用   查看     
#31楼 2010-06-27 16:04 | pqmagic       
引用ouzi:
2. socket在传输过成功,不同时间发送的数据包有可能被合并,同时到达了客户端,这个就是黏包问题。例如发送方发送了hello+world,而接收方可能一次就接受了helloworld.

其实我认为TCP只要你的协议定好了,是没有黏包问题的,因为你有包头,长度,包尾,可以分割,其实在我认为不好处理的,应该是分包不好做,不过我们公司好像分包就像上面的回复那样,是把分的包给丢了的,唉。。。

个人觉得粘包和分包现象,应该由tcp传输层协议所决定的,跟网络包、应用层协议无关吧。

   回复   引用   查看     
#32楼 2010-06-27 16:11 | pqmagic       
引用ouzi:
不过我还是比较幸运的,基本上没有做过什么***管理系统之类的,一毕业就做起了通讯,这块,发现确实比较麻烦,不过用C#做服务器的话,我们主管说,性能还是不错的,做通讯在高层更多的感觉是做策略,比较udp的重发机制等等,在底层的话,就是2进制流的转来转去,

@pqmagic
我试着回答一下,可能没有办法做你说的那种类型检查了,做通信,就是做协议,有了协议别人不遵守,那就项目没有办法做了

我没有看过一些好的RPC协议规范,但像webservice,wcf无非也是把远程方法调用所需要的方法名、参数、返回值、类型以xml的形式封装成一个网络包,由接收方解析;并转换成相应的类型,最后调用远程方法。
这些通用的协议,有明显的好处在于通用性强(比如wcf可以根据逻辑和协议直接生成客户端代理类),但个人觉得也太重量级了,一次简单的调用,所需要传输的“无意义”数据,几乎占了整个网络包的2/3

   回复   引用   查看     
#33楼 2010-06-27 16:11 | 亚历山大同志       
@pqmagic
TCP协议中的内容是一个二进制流,所以就TCP协议本身来说是无所谓粘包问题的,所有数据对TCP协议而言都是一串2进制的流,它只需要保证流的顺序正确和完整性就可以了,粘包问题是以TCP为基础的上层协议要解决的问题。

   回复   引用   查看     
#34楼 [ 楼主]2010-06-27 16:13 |        
@萨肯

主要是exception不是我们业务代码抛出来的,而是.net框架抛出来的。

比如一个File操作,如果文件不存在就会抛出IOException。

因此为了减少exception,必须对输入做全方位的验证,提高性能。

   回复   引用   查看     
#35楼 2010-06-27 17:40 | zzfff       
没做过,但能想象出一点,发点bia言。
最重要的:不要自定义协议!
最重要的:不要自定义协议!
最重要的:不要自定义协议!
比如,TCP是流式的,如何framing?别想着DIY,用现成的协议,对于我,很快就找到答案:微软定义了[MC-NMF]: .NET Message Framing Protocol Specification,WCF中的SOAP over TCP就是用了它。
ok,“你”会说,M$可以DIY,我就不能?.............................................................

   回复   引用   查看     
#36楼 2010-06-27 18:08 | zzfff       
我不是个严谨的人,感觉binary XML + SOAP over TCP性能不会差得离谱,“性价比”却比raw socket programming高N倍。
   回复   引用   查看     
#37楼 [ 楼主]2010-06-27 18:21 |        
@zzfff

问个问题,如果用MS的,那是否就意味要用MS提供的收发dll?

如果是,那如何同flash交互?同java、php之类的交互?

如果不能,那就只能和silverlight了。那么不就意味着自己的业务被完全局限在了MS的狭小空间了?webgame做不了、flash的一切应用做不了,sl目前根本不普及(是一点点普及都没有)。

   回复   引用   查看     
#38楼 2010-06-27 18:47 | zzfff       
@辰
只用MS的协议,你可以自由的实现。protocol与implement是截然不同的东西。说到这,这得怪标准化组织(IETF,W3C...)的不作为,比如binary XML,SOAP over TCP等,具我所知,根本没进行标准化工作,M$是商业公司,不得已,当然只有自己DIY了,好像也有其它组织也做了与M$竞争的协议。说到底,用最牛公司/组织的协议而不是DIY。

   回复   引用   查看     
#39楼 2010-06-27 18:47 | Curry       
6. 服务器短时间发送信息激增:有可能在服务器内部处理逻辑中,突然产生了海量的数据需要发送,例如游戏中的“群发”;因此必须对发送进行队列缓存,然后进行合并发送,减轻socket的负荷。

___
能不能解释下进行合并发送,这个具体怎么操作?

   回复   引用   查看     
#40楼 2010-06-27 19:02 | zzfff       
也许我太纸上谈兵,也许我太完美化,在我看来,在21世纪已经过了9.5年的今天,network application没interoperability是致命的,嗯,大多数人都“尿”的协议,SOA........
   回复   引用   查看     
#41楼 2010-06-27 19:25 | zzfff       
这是个权衡妥协的问题:对于项目,自定义协议,quick and dirty上马;如果想做产品,或有所追求,这就得好好考虑了。
   回复   引用   查看     
#42楼 2010-06-27 21:38 | 常言不哭       
从来没涉及到这方面的内容,先MARK一下,感谢LZ分享。
   回复   引用   查看     
#43楼 2010-06-28 00:15 | 依落の守候       
mark一下,受教了。
   回复   引用   查看     
#44楼 2010-06-28 03:30 | 横竖都溢       
一直以来,都对TCP/UDP的通讯编程有很强烈的兴趣,所以,关注你的博客。
   回复   引用   查看     
#45楼 2010-06-28 07:24 | meslog       
受教了,感谢作者,期待下一篇文章,
   回复   引用   查看     
#46楼 2010-06-28 09:52 | 爱在两腿间       
关注 希望楼主能坚持写完这个系列
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值