DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: guang2022
今日帖子: 6
在线用户: 1
导航: 论坛 -> 网络通讯 斑竹:liumazi,sephil  
作者:
男 fuhoutun (fuhoutun) ▲▲▲▲▲ -
注册会员
2020/10/28 6:57:00
标题:
请问IdTCPServerr最多能连多少个客户端? 浏览:1947
加入我的收藏
楼主: 请问IdTCPServer最多能连多少个客户端?谢谢!如何实现IdTCPServer能连尽量多的客户端?
----------------------------------------------
-
作者:
男 feiyanm (feiyanm) ▲▲▲▲△ -
注册会员
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吐一会儿去!
作者:
男 feiyanm (feiyanm) ▲▲▲▲△ -
注册会员
2020/10/28 10:02:25
2楼: 这里有一些相关的性能测试,仅供参考:
https://blog.csdn.net/yayongm/article/details/79868146
----------------------------------------------
Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!我去WC吐一会儿去!
作者:
男 bahamut8348 (leonna) ★☆☆☆☆ -
普通会员
2020/10/28 11:48:48
3楼: 理论上,最多同时支持65536个端口,那么也就最多支持65536个client端同时在线。
但是实际情况下,单机至多能支持到3万个连接左右就是极限了。这个不单是什么线程、端口的因素,还有cpu、内存等方面的制约。
不过一般情况下,长连接超过10000以后,就都会上集群了。
----------------------------------------------
--
作者:
男 fuhoutun (fuhoutun) ▲▲▲▲▲ -
注册会员
2020/10/28 12:58:25
4楼: 谢谢3位高手,但我的IdTCPServerr程序,当客户端达到大约20时,新的客户端试图登录时,新的客户端显示“connection closed gracefully”,请高手们帮我分析一下可能是什么原因,万分感谢!
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2020/10/28 17:11:38
5楼: 你可以拿你的 SERVER 程序在 DEBUG 模式下跑起来看看出问题的时候究竟里面是出了什么问题。

你这样的问题,没看到代码,没法分析。
----------------------------------------------
-
作者:
男 bahamut8348 (leonna) ★☆☆☆☆ -
普通会员
2020/10/28 17:50:02
6楼: 一直没用过indy的东西,看看是不是有哪个属性限制了最大连接数。
不过具体看你的负载预计有多少,太多的话起码要上iocp。
----------------------------------------------
--
作者:
男 hnxxcxg (咏南中间件) ★☆☆☆☆ -
盒子活跃会员
2020/10/28 19:52:50
7楼: 赞同5楼,摆事实,讲证据。
----------------------------------------------
中间件QQ群: 92449782 博客: http://www.cnblogs.com/hnxxcxg/
作者:
男 fuhoutun (fuhoutun) ▲▲▲▲▲ -
注册会员
2020/10/29 6:32:52
8楼: 各位高手说得对,没看到代码,没法分析,附件是IdTCPServerConnect事件登录部分的代码,请各位高手指教。
此帖子包含附件:fuhoutun_2020102963355.txt 大小:3,896B
----------------------------------------------
-
作者:
男 ghs_79 (ghs) ★☆☆☆☆ -
盒子活跃会员
2020/10/29 15:47:57
9楼: 给的代码也运行不起来,不想补充了。
按如下调整看会快多少
1、取判断用户是否存在、密码是否正确,一个过程就够了。按用户名去返回密码(不要全表取数据),返回有记录了,就说明用户存在,再判断密码是否正确。一次查询且只返回一条记录就解决了。
2、通知界面刷新改为PostMessage试试
----------------------------------------------
Delphi爱好者。
作者:
男 scarlette (Scarlette) ★☆☆☆☆ -
普通会员
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要好。
----------------------------------------------
-
作者:
男 jackalan (nVicen) ★☆☆☆☆ -
盒子活跃会员
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完全可以合并成一次查询验证的为啥分开来,搞两次初始化、连接数据库、查询、销毁。。。
----------------------------------------------
简单做人,认真做事。
作者:
男 bahamut8348 (leonna) ★☆☆☆☆ -
普通会员
2020/10/30 9:51:33
12楼: @scarlette (Scarlette)
当然说的就是出的,其实在实际情况中,更多的可能是cpu或者内存受限,并不是端口受限,毕竟server端是要处理业务的,只测试空链接没什么太大意义。

看楼主的业务处理就挺坑爹的,不说别的,单说每次链接都要重新连接一次数据库就太坑爹了,这里起码要用一个连接池来处理。这种方式IO次数太多,太占资源了。
而且一般判断用户身份都不会分次去判断,一般都是一次性查询,username=?? and password = ??,只要空记录就直接返回“账号或密码错误!”就完事了,哪里需要这么麻烦。
----------------------------------------------
--
作者:
男 scarlette (Scarlette) ★☆☆☆☆ -
普通会员
2020/10/30 11:19:40
13楼: @bahamut8348 (leonna):
他一开始问的不是indy server能连多少客户端么……
他那个每次重置connection玩法,直接带沟里去了啊。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
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 了。
----------------------------------------------
-
作者:
男 fuhoutun (fuhoutun) ▲▲▲▲▲ -
注册会员
2020/11/2 11:25:50
15楼: 非常感谢9楼到14楼各位高手的指教,你们如此此认真地分析我的菜代码,非常感动!我在按你们的指教,慢慢试,情况有所好转,再次感谢!
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
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 里面取一个对象实例时,要加锁。

到这里基本上就搞定了。
----------------------------------------------
-
作者:
男 fuhoutun (fuhoutun) ▲▲▲▲▲ -
注册会员
2020/11/6 5:45:38
17楼:  非常感谢高手pcplayer的耐心指教,我在按你的指教试。
----------------------------------------------
-
作者:
男 fuhoutun (fuhoutun) ▲▲▲▲▲ -
注册会员
2020/11/7 5:37:57
18楼: 非常感谢各位高手的耐心指教,我按你们的指教将代码进行了一些优化,情况有所改善,但连接超过66个客户后仍然出错,后尝试将IdTCPServer的MaxConnection属性从默认值0改成100,连接100个客户没问题,我又将其改成200,连接200个客户也没问题。一般认为默认值0是不限制客户数,但为什么会出现以上情况,没法解释。我的问题解决了,再次感谢各位高手!
----------------------------------------------
-
作者:
男 tuhemm (刀锋土禾) ▲△△△△ -
禁用账号
2022/5/12 22:56:56
19楼: ……
被禁用帐号,帖子内容自动屏蔽!
……

----------------------------------------------
发布无用信息,禁用帐号!
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v2.1 版权所有 页面执行117.1875毫秒 RSS