下载代码:
http://upload.programfan.com/upfile/200705302206138.rar根据网络上“一个修改了的IOCP例子”改写的IOCP for DELPHI版本,做简单测试的时候没有什么问题,就比如用里面的client.exe能够正常发送接收数据包,正常退出;用里面的ClientIOCP.exe进行压力测试,ClientIOCP.exe IP地址 IP端口;然后输入发送的信息,连接数为60,每个连接发送60000次,服务器都能够正常运行,如果你有耐心,等这些60*60000次一直在运行,服务器都很正常;如果没有客户端连接,且客户端没有发送数据了,这个时候点击“服务停止”则能够正常关闭服务器;为了测试在有客户端连接,或者客户端还在发送数据接收数据的情况下,里面的“服务停止”是否能够正常关闭服务器【你可用ClientIOCP.exe发个60个连接,每个连接60000次】,这个时候你去点击“服务停止”按钮,则服务器在GetQueuedCompletionStatus出现了问题,其返回为FALSE,通过GetLastError得到错误码为6;而且一直没完没了地在执行getQueuedCompletionStatus..........不知道问题出现在哪里?

解决方案 »

  1.   

    咋没人回答啊??
    刚刚对程序进行跟踪了一下,发现问题在于在还有客户端连接或者发送接收数据的情况下,停止服务,首先是出现一个10093的错误,这个错误有时是由程序里面的setsockopt引起,有时是由于wsarecv引起,有时是由于wsasend引起的;最后都导致getque......的时候出现6的错误。
      

  2.   

    楼主最大的问题,出现在访问VCL(MainForm当中的Memo)执行的是非线程安全的代码。
      

  3.   

    楼主的代码,我测试过了,主要是线程冲突引起的:
    建议1:为了能使用TThread当中的VCL主线程同步函数,建议不要直接使用CreateThread,而使用TThread类来实现线程,这样子方便应用,否则的话对VCL的访问会有问题。
    建议2:如果需要使用CreateThread的话,建议显示数据使用一个线程安全的列表对象保存消息内容队列,然后再由主线程自己调用一个Timer来显示数据,或者直接写文件Log.
      

  4.   

    To unsigned:     我现在用了线程同步了,而且是继承Tthread的方法;
         可是还是有问题啊,在GetQueuedCompletionStatus上一直返回FALSE,但是getlasterror确是0;     新的代码在
         http://upload.programfan.com/upfile/200706021603829.rar     你帮我看看,看问题在那里,帮我解决一下;winsock2.pas我是用JEDI上的【大家说这个好】,可以到这里下载ftp://ftp.delphi-jedi.org/api/Winsock2.zip;因为我原来安装winsock2.pas是安装在公共目录里面,所以你编译的时候,把里面对winsock2.pas单元的引用更改成你的路径;     郁闷好几天了。
      

  5.   

    To unsigned:      补充一下,程序在简单测试的时候都很正常;
          就是在压力测试的时候【用里面的clientiocp.exe发个60个连接,每个连接发6000次,这个时候够让服务器忙一会儿了】,在服务器忙的时候,点击“服务停止”后就出现我上面说的问题了。
      

  6.   


           现在搞定了.       主要问题是在于要等待工作者线程停止工作了后,再Wsacleanup();       原来其实也用了WaitForMultipleObjects和MsgWaitForMultipleObjects等这些线程同步的方法,可是不知道为什么一直没等到工作者线程停止WaitForMultipleObjects和MsgWaitForMultipleObjects就返回了,结果就执行后面的Wsacleanup()了,而这个时候完成端口的队列里面还有表项,继续getque,而Wsacleanup已经执行了,所以导致getque...返回了FALSE,而getlasterr却是0;
           现在在等待工作者线程停止的时候采用:    While(TRUE) do
        begin
             bret:=MsgWaitForMultipleObjects(1,g_hWorkerThreads,FALSE, INFINITE, QS_ALLINPUT);         if( (bret = WAIT_OBJECT_0) ) then
              begin
                  break;
              end
             else
              begin
                  PeekMessage(Msg, 0, 0, 0, PM_REMOVE);
                  DispatchMessage(msg);
              end;
        end;如果有多个工作者线程,则复制上面的代码,对每个工作者线程等待一次;如果在这个循环里面有对VCL控件的一些操作,比如说你想在memo里面显示日志,比如加个form1.memo2.lines.add('等待关闭'),这种情况下就会出现getque.....返回FALSE的死循环的情况;这可能是因为form1.memo2.lines.add也会产生一些消息,结果出现意想不到的一些问题;
       现在我在这个循环里面不加任何的日志显示【就是不对任何VCL进行操作】,则不会出现任何问题了。   现在不管怎么测试,都一切正常了;
       谢谢大家的回复。
      

  7.   

    楼主,能发一份代码给我吗?本人对IOCP一点也不懂,想学习一下.