导航:
论坛 -> 网络通讯
斑竹:liumazi,sephil
作者:
2020/10/28 6:57:00
标题:
请问IdTCPServerr最多能连多少个客户端?
浏览:2516
加入我的收藏
楼主:
请问IdTCPServer最多能连多少个客户端?谢谢!如何实现IdTCPServer能连尽量多的客户端?
----------------------------------------------
-
作者:
2020/10/28 9:56:53
1楼:
Win32:最多5990线程,超过不稳定。 Win64:应该是无限。 实际上,因为操作系统对线程调度的问题,并不是线程越多性能越好。 所以,如果需要高性能服务器,强烈不建议使用Indy!!! 有http需求的话,可以看看: http://www.moonserver.cn/mhs/single-post.pp?id=68&catalog=1
----------------------------------------------
Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!我去WC吐一会儿去!
作者:
2020/10/28 10:02:25
2楼:
这里有一些相关的性能测试,仅供参考: https://blog.csdn.net/yayongm/article/details/79868146
----------------------------------------------
Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!我去WC吐一会儿去!
作者:
2020/10/28 11:48:48
3楼:
理论上,最多同时支持65536个端口,那么也就最多支持65536个client端同时在线。 但是实际情况下,单机至多能支持到3万个连接左右就是极限了。这个不单是什么线程、端口的因素,还有cpu、内存等方面的制约。 不过一般情况下,长连接超过10000以后,就都会上集群了。
----------------------------------------------
--
作者:
2020/10/28 12:58:25
4楼:
谢谢3位高手,但我的IdTCPServerr程序,当客户端达到大约20时,新的客户端试图登录时,新的客户端显示“connection closed gracefully”,请高手们帮我分析一下可能是什么原因,万分感谢!
----------------------------------------------
-
作者:
2020/10/28 17:11:38
5楼:
你可以拿你的 SERVER 程序在 DEBUG 模式下跑起来看看出问题的时候究竟里面是出了什么问题。 你这样的问题,没看到代码,没法分析。
----------------------------------------------
-
作者:
2020/10/28 17:50:02
6楼:
一直没用过indy的东西,看看是不是有哪个属性限制了最大连接数。 不过具体看你的负载预计有多少,太多的话起码要上iocp。
----------------------------------------------
--
作者:
2020/10/28 19:52:50
7楼:
赞同5楼,摆事实,讲证据。
----------------------------------------------
中间件QQ群: 92449782 博客: http://www.cnblogs.com/hnxxcxg/
作者:
2020/10/29 6:32:52
8楼:
各位高手说得对,没看到代码,没法分析,附件是IdTCPServerConnect事件登录部分的代码,请各位高手指教。
----------------------------------------------
-
作者:
2020/10/29 15:47:57
9楼:
给的代码也运行不起来,不想补充了。 按如下调整看会快多少 1、取判断用户是否存在、密码是否正确,一个过程就够了。按用户名去返回密码(不要全表取数据),返回有记录了,就说明用户存在,再判断密码是否正确。一次查询且只返回一条记录就解决了。 2、通知界面刷新改为PostMessage试试
----------------------------------------------
Delphi爱好者。
作者:
2020/10/29 22:19:00
10楼:
@bahamut8348 (leonna): Inbound链接不受端口数限制,Outbound才受动态端口可分配数量限制,Windows 10上实测大约16K+。 Inbound链接数量实际上受到几个因素共同影响,主要是Winsock 2和NIC provider自身设计决定的。我实测单个IOCP Port绑定单个TCP Port,inbound链接50K+时候开始会不定期少量断链(回报的Error code也有点莫名其妙),而且不同网卡驱动会有差异,intel i210明显比Realtek 8111要好。
----------------------------------------------
-
作者:
2020/10/30 9:39:31
11楼:
看到满屏的LOCK头都晕, 这段更是看不懂 Client.Lock; try Client.Context.Connection.IOHandler.WriteLn('LOGINED' + ' ' + IntToStr(lvUsers.Items.Count)); finally Client.Unlock; end; 明明能直接用AContext的为什么要LOCK然后从列表中取? 明明可以直接用lst取Counts的或者直接用CCount数据的为什么要去读UI的数据:lvUsers.Items.Count ReadUserName和Pass里面已经加了锁,外面又FLOCKUI加锁。。。 明明可以在 SELECT * From UserInfomation where username=xxxx SELECT * From UserInfomation where username=xxxx and Pass=xxxx 一次性完成查询的,为什么要用while再去循环比较? ADOQuery.SQL.Add('SELECT * From UserInfomation'); ADOQuery.Open; while not ADOQuery.Eof do begin MyString:=ADOQuery.FieldByName('Pass').AsString; if (MyString=PassW) then Result:=true; ADOQuery.Next; end; 为什么这个select没有加条件?where username=xxxx 你这样取出来的是全体人员,然后不管哪个人,只要密码对就行? ADOQuery.SQL.Add('SELECT * From UserInfomation'); ADOQuery.Open; while not ADOQuery.Eof do begin MyString:=ADOQuery.FieldByName('Pass').AsString; if (MyString=PassW) then Result:=true; ADOQuery.Next; end; ReadUserName和ReadUserPassW完全可以合并成一次查询验证的为啥分开来,搞两次初始化、连接数据库、查询、销毁。。。
----------------------------------------------
简单做人,认真做事。
作者:
2020/10/30 9:51:33
12楼:
@scarlette (Scarlette) 当然说的就是出的,其实在实际情况中,更多的可能是cpu或者内存受限,并不是端口受限,毕竟server端是要处理业务的,只测试空链接没什么太大意义。 看楼主的业务处理就挺坑爹的,不说别的,单说每次链接都要重新连接一次数据库就太坑爹了,这里起码要用一个连接池来处理。这种方式IO次数太多,太占资源了。 而且一般判断用户身份都不会分次去判断,一般都是一次性查询,username=?? and password = ??,只要空记录就直接返回“账号或密码错误!”就完事了,哪里需要这么麻烦。
----------------------------------------------
--
作者:
2020/10/30 11:19:40
13楼:
@bahamut8348 (leonna): 他一开始问的不是indy server能连多少客户端么…… 他那个每次重置connection玩法,直接带沟里去了啊。
----------------------------------------------
-
作者:
2020/10/30 17:27:53
14楼:
11 楼说得很对。 这个 OnConnect 的代码就一堆问题。估计 OnExecute 里面的代码问题更多。 简单点说,目前楼主碰到的连接数不够,就是代码的问题导致的。代码消耗了太多的系统资源。 那些 Lock 看起来没有意义,并且,会让多线程的并发连接,变成一个一个排队执行。楼主在这里是临时创建的 ADOConnection 也就是说每个线程有自己的 ADO 实例,根本不需要 Lock,除非是所有线程共用了同一个 ADO 实例。 至于 12 楼说的数据库连接池,是为了不要每次 TCP 连接来了都要去创建一次 ADO 实例并建立一次数据库连接,这样会节约很多系统资源包括 CPU 时间。 然后 13 楼说的问题,我仔细看了一下楼主的代码,大概是指这个: for i := 0 to lst.Count - 1 do begin if SameText(TUser(lst[I]).UserName, AUserName) then begin AContext.Connection.IOHandler.WriteLn('USER_ALREADY_LOGINED'); AContext.Connection.Disconnect; Exit; end; end; 上述代码,我没看明白楼主想要干什么。在 OnConnect 事件里面,执行 AContext.Connection.Disconnect,那就是把这个客户端连接断开。 结果就是客户端的 TCP 一连上服务器就被断开了,TIdTCPServer 都没机会执行 OnExecute。所以不我看不明白这段代码的意思。总之就是断开连接了。 最后提醒:TIdTCPServer 有个 MaxConnections 属性,默认是 0 .如果不小心改成了20,那你的最大连接数就是 20 了。
----------------------------------------------
-
作者:
2020/11/2 11:25:50
15楼:
非常感谢9楼到14楼各位高手的指教,你们如此此认真地分析我的菜代码,非常感动!我在按你们的指教,慢慢试,情况有所好转,再次感谢!
----------------------------------------------
-
作者:
2020/11/2 19:06:00
16楼:
楼主,你的代码,我觉得: 1. 不要在 OnConnect 里面搞。直接在 OnExecute 里面搞; 2. 在 OnExecute 里面,不要搞什么 Lock 之类的东西。如果在里面需要动到界面元素,仅仅在动界面元素的地方,加上同步主线程的方法; 3. 每次数据库操作(ADOConnection, ADOQuery),都用独立的实例,然后加上缓冲池,实例从缓冲池里面取,而不是每次都重新创建,重新建立数据库连接。 ---------- 缓冲池,看起来好像很高大上,其实很简单。你可以这样做: 1. 做一个 TDataModule,把你的 ADOConnection 和 ADOQuery 之类的东西都放进去,把操作数据库的业务逻辑代码都放进去,在 Public 部分留下接口函数,让 OnExecute 里面的代码去调用就可以了。 2. 再搞一个 TDataModule,目的是程序启动时自动创建。你如果自己做一个类,然后在程序启动时创建那个类的实例,也可以。这个模块,就是【池】。这个池,可以很简单,就是搞一个 Array 或者 List 之类的东西,创建几个第一个 DataModule 的实例,放在 List 里面。你的 OnExecute 需要用数据库的时候,从这个池里面取一个实例出来,用完放回去。 2.1. 因为 OnExecute 是多线程并发的,所以从上述 List 里面取一个对象实例时,要加锁。 到这里基本上就搞定了。
----------------------------------------------
-
作者:
2020/11/6 5:45:38
17楼:
非常感谢高手pcplayer的耐心指教,我在按你的指教试。
----------------------------------------------
-
作者:
2020/11/7 5:37:57
18楼:
非常感谢各位高手的耐心指教,我按你们的指教将代码进行了一些优化,情况有所改善,但连接超过66个客户后仍然出错,后尝试将IdTCPServer的MaxConnection属性从默认值0改成100,连接100个客户没问题,我又将其改成200,连接200个客户也没问题。一般认为默认值0是不限制客户数,但为什么会出现以上情况,没法解释。我的问题解决了,再次感谢各位高手!
----------------------------------------------
-