yao_ming
37586
|
2009/5/26 20:02:08 |
Good,没弄明白,回头下你的源代码学习一下。 to unsigned,你上面的话其实已经考虑到非100%正确的逻辑了。 |
aknightchen
37125
|
2009/4/8 15:28:23 |
感谢楼主共享代码! |
unsigned
37100
|
2009/4/5 15:59:55 |
程序员的逻辑未必就是最终用户的逻辑,写程序是服务于用户的,而不是服务于逻辑的。也许你的逻辑拥有100%的可行性,但是在用户的环境里面可能就不是如此,比如我们前段时间碰到的一个问题,我们接入到三方的系统,但是三方的系统返回的时候当中存在着不符合协议的数据包,他们的协议边界使用的是一个ASCII字符,而实际返回的数据当中,由于其中一个汉字被截取到一半,从而被截取剩余的半个汉字刚好与该边界字符组成了一个新的汉字,从而导致返回的数据已经是不符合原设计逻辑的协议包。如此安全遵照程序员的逻辑,那么这个问题应该是由责任方去修正,但是这个修正不仅需要花费大量的人力物力还需要时间,在这种情况下,你的逻辑就不再能够得到保证。 |
138soft
37081
|
2009/4/3 1:11:17 |
由于程序运行的环境几乎99.99%都不是在开发机器上,从而几乎所有程序员都会一种疑滤:不可能100%了解目标环境所有问题的可能性。
逻辑正确,结果一定会正确.自己写的代码如果都不清楚流程,则是可怕的. |
unsigned
37017
|
2009/3/29 17:55:54 |
极大部分程序员都会有一个自信:程序不会存在问题,但是事实上任何一个程序员都不可能100%保证自己的程序没有问题;由于程序运行的环境几乎99.99%都不是在开发机器上,从而几乎所有程序员都会一种疑滤:不可能100%了解目标环境所有问题的可能性。
我只能说,那些把话说得理直气壮的程序员,只是一个无知。 |
unsigned
37016
|
2009/3/29 17:47:51 |
To 138soft,结构化异常处理应该是一个好的习惯,而不是不好的习惯,只是不可以滥用。当存在与外部的交互,包括任何的API等等,都可能存在不可预测的情况。另外就是函数/过程的深度加深时,异常是最好的处理方法。良好的编码对于个人是可以达到保证的,但是对于团队开发,就不再是那么容易的事。只要稍稍有某一个分支出现非预期的结果,而这个结果在整个程序的运行逻辑上是无关紧要的,如果使用结构化异常,则可以很好地保证程序的健状性,但是如果不使用结构化异常,则可能导致不可预测的后果,比如造成用户数据的完整性等等。一个逻辑从无到有的产生,并不是偶然的,如果它的存在是不合理的,那么就不会再被延续,换句话说它的生命周期就应当得以终结,但是事实上存在着就会有两面性,关键就看如何合理利用。 |
peliao
37010
|
2009/3/28 17:27:54 |
建议网上用delphi写IOCP封装的,
要测的话,
自己写个demo,这个写,保证几分钟就报错,av,退出之类的 client: 7个线程建立连接,并发送数据,3个线程随机关闭建立好的连接 server: 随机随时主动断开连接 |
138soft
37008
|
2009/3/28 12:12:45 |
看来我的出手了... 很多人根本就没有真正了解什么叫IOCP. 还有,使用try except 本身是个不好的习惯.应该改掉. 只要你的逻辑是正确的,根本就无需要使用什么异常捕获.我就从来不用. |
unsigned
37006
|
2009/3/27 13:37:19 |
To geoman,其实使用对于并发连接,在IOCP中可以通过增加线程来执行accept/WSAAccept,或者最好是同时投递多个AcceptEx来达成,一般应用当中AcceptEx都不需要预接收数据,只接受连接就好了。由于是做测试,所以压力是相当大的,同一时间发起连接,有连接不上是正常的,实现的应用当中这种情况是比较少见的,对于以短连接为主的应用,个人建议如果能够就改用UDP,或者大幅提升AccetEx的数量。
listen的那个backlog实际意义并不大,要么是服务器的资源已经达到饱和,要么就是能够参与accept的线程数量不够,在winsock1.0当中实际上backlog的最大值是相当小的,winsock2进行了扩充,而实际上winsock2在底层实际上已经是做了accept操作,可以试着只开Listen,而不开accept线程,然后telnet到该端口。 ========== 楼主做的这个封装还是只能算是个雏形,要达到实用性还需要相当多的改造,比如这里对主动收发操作并没有做封装,对于一应一答式的服务也许足够了,但是对于有主动推送,或者一问多答等等就相当麻烦,必须要加以控制。 对于内存管理,最好都改用HeapAlloc/Heapfree等堆内存操作函数,而不要有些地方使用GlobalAlloc,另外的地方又使用GetMemory,如此混用将会导致一个后果,那就是在某些情况下可能会调用错误的内存管理函数。使用IOCP本意是高效率,那么内存池是必不可少的,否则一个七剩二十四小时运行的系统,很容易因为内存碎片导致无法正常工作,或者性能严重下降。 |
skywings
36975
|
2009/3/23 10:47:28 |
正好要搞IOCP,学习学习。 |
geoman
36960
|
2009/3/20 23:43:40 |
改了listen(Listensc,20);可以连上了200,但cpu占用率有11-30% |
myhhs2009
36958
|
2009/3/20 21:58:30 |
关键在于测试的方法.个人认为IOCP只是一种传说.当用户量上升到2000左右,就有这样或那样的可能.没有丰富的经验,很难驾驭的. |
qiuyan81
36957
|
2009/3/20 18:14:15 |
listen(Listensc,20); 说错了 是这个 |
qiuyan81
36956
|
2009/3/20 18:04:25 |
那个是并发连接请求的时候最大队列。 |
qiuyan81
36955
|
2009/3/20 18:03:22 |
把accept的第二个整形参数设置大点就行了。 |
geoman
36954
|
2009/3/20 17:33:31 |
还有问题,并发200连接只能连接32个,本机测试,但网上其他的共享代码最少能连100多,也有能全连上的,建议参考DBIOCP代码和小牛远控中的IOCP代码,再次谢谢楼主的共享精神 |
ke8880
36951
|
2009/3/20 12:03:18 |
这个我知道啊,但这个参数只在OnRead事件中才能读取吧?
当客户连接数一多时,就需要对这些连接进行统一管理,我描述的TClientLinks就是用于保存所有客户端连接信息的。 |
qiuyan81
36950
|
2009/3/20 11:54:21 |
PLinkInfo这个结构指针里面就存有客户信息。 自己扩充下就好。 |
ke8880
36949
|
2009/3/20 11:50:23 |
我发现IOCPSever有一个LinkCount属性,记录当前客户端的连接数,能否增加一个客户端连接对象,用于记录所有的在线的客户端连接对象?
当然用户在编程时可以自定义创建这样的对象,但是如果控件能预封装这个对象,操作起来会更加方便。我建议第个客户端连接对象的数据结构如下: TClientLink=record Skt: Integer; LinkInfo:PLinkInfo; Data:Pointer; //用户自定义数据 end; |
qiuyan81
36948
|
2009/3/20 11:31:10 |
是的,你只要把指针头传进去,再传发送大小就OK了。 |