用异步 socket API来编写一个服务器程序,可以同时接受多个客户端的连接,并把客户端上传的数据写入数据库。
客户端的数量可能有很多。10个以下时,程序操作很流畅,当加到20个时,反应就有点慢了,到30个时,打开菜单差不多要3秒多。每个客户端随时都有可能有数据在上传,数据不能丢,但界面反应速度也不能太慢
看了emule的代码(还没全看完),是C++的,VC.net装不起来,没办法编译看实际效果。
程序是用Delphi6写的,不可能改用C/C++了。想问一下,Delphi里是不是所有的消息都要先发到程序主窗口?我另外单独建立了一个窗口用来接收Socket的异步通知消息,这些消息是不是也先到主窗口经过才能收到?如果有提高界面反应的好办法,也请说一下

解决方案 »

  1.   

    用线程就行了,indy那套东西都可以用
      

  2.   

    我是用线程做的,没有用Indy,是修改自 eMule的一套自定义Socket收发类。处理入库和发回结果都是用单独的线程,接收用的是消息处理函数,用 WSAAsyncSelect选择通知消息,再在消息处理函数中调用接收函数的。只有这部分可能是在主窗体的线程里了。
      

  3.   

    是不是可以做一个队列,socket接收写队列,线程读队列入库。主窗口写队列应该很快。不会影响界面的刷新
      

  4.   

    WSAAsyncSelect这同主窗体什么的不相干,主要是消息由主线程的消息循环处理.
    这样很明显会拖慢界面反应.方法一,换用其它IO方式方法二,另创建一个工作线程,由这线程里创建WSAAsyncSelect所需要的窗口句柄,
    也就是由它来专门处理这方面消息循环.
      

  5.   

    我的看法:
    用了线程界面反映还慢,估计是因为操作数据库的代码还是同步到主线程了。
    用连接池和query池,1是省去建立连接的时间,2可以放到线程里,不用切换到主线程,速度快,界面也不会受到影响了。
    处理消息的代码30个客户端不会对主界面造成那么大的影响吧。
      

  6.   

    开一个缓冲区堆,将所有SOCKET收到的数据先保存在缓冲区堆中,然后在用一个单独的线程来将缓冲区中的数据保存,而不是直接将收到的数据写到数据库中.只要是窗体就可以收到消息.
    FWinHandle :=Classes.AllocateHWnd(WndProc);为它来创建一个不显示的窗体.在WndProc中处理消息.
      

  7.   

    我是用 CreateWindow来创建的窗口,处理命令和入库是一个线程,返回命令结果也是一个线程,现在能改的可能也就是 halfdream(哈欠)  的第二个馊主意,在线程里来创建窗口和处理接收到的消息了。我自已觉得接收消息那一块代码还是比较少的,应该比较快。接20台机器和接30台,效果差别太大了。老大的目标可是要100台
    另外,问一下,同一个程序里能开的Socket最多能有多少个?MySQL 好象最好能开1万多个,不会有这么多吧
      

  8.   

    速度快慢和代码多少并不是成比例的.消息接收窗体创建一次就可以了吧.SOCKET可以开很多,但如果不工作的话只是占用点空间,不会对系统造成影响的.
    只有在收到数据时系统才将数据接收到SOCKET缓冲区,然后给你的程序发消息,程序将数据读出来保存,如果你不能很快将系统SOCKET缓冲区中的数据处理的话就会占用系统资源.
    所以最好还是将SOCKET收到的数据尽快的转移到自己的缓冲区中,然后创建工作线程从自己的缓冲区中读取数据处理,如果数据实在是太多可以将缓冲区内存分配的大一些或者先将数据保存成文件,然后在后台慢慢处理.在就是如果读写数据库频繁的话最好建立连接后不要释放更复杂一点的方法就是用IO映射,让系统直接将SOCKET接收到的数据放到你的缓冲区中,这样就避免了一次搬移数据的过程.你只要支持100多用户我想根本用不着用端口映射.
      

  9.   

    找到一点思路了,在线程的 Execute 里执行创建接收消息的窗口,这样就可以在线程里处理消息,不占用主程序了。在线程的Create 里创建的窗口还是会占用主窗口的。
    不过这样就要把原来的处理过程做许多修改,把涉及到界面的部分用Sync...的调用包起来,不是一时半伙做得完的。
      

  10.   

    如果要将从线程的执行情况在主线程中显示,最好是发Post消息给主线程,而不要调用Synchronize在线程的Create里创建窗口也并不会占用主窗体的什么.你的理解我觉得还是不对.应该是创建窗体,在窗体收到网络消息后将SOCKET发来的数据接收,然后将接收到的数据交给工作线程去处理,在处理的过程中工作线程发送消息给主窗体让它来显示.如果没有数据到来则工作程序暂停
      

  11.   


    有一点楼主别弄错,TThread.Create 这方法的执行是在你调用的线程,也就是主线程!!!
    只有在Execute方法里才是对应的工作线程.另外,强烈建议楼主把线程里面Sync...什么的语句去掉..那些代码同样会拖慢主线程.
    在工作线程处理的时候,就不要去调用界面上实时显示的功能!!
      

  12.   

    我现在把接收Socket通知消息的窗口在工作线程Thread.Execute里创建,接上40多个设备时响应速度跟10个时差不多,可以接受了。但如果是在 thread.Create 里创建,响应速度马上就下来了。
    现在剩下来的就是些零星的小问题了,主界面更新时自已去取更新了的数据,工作线程只负责处理,有变化时也不去通知主界面了。照现在看,接上100个应该问题也不大。
    只是程序里指针、结构体用多了,小错误不断,还得改