我在用TTcpServer的时候发现如果Client端发送太快时,server端就会被堵死,查看delphi线程跟踪,发现死在一个循环里了,因为是汇编语言,不是很清楚,但是可以发现是关于sock的。这时候的现象是cpu占用率100%,客户端仍然在发送,但是server端已经不再接收。此问题困扰好久了,非常着急,系统因为这个几天就死一次,导致项目没有办法验收,本人被困在现场好几个月了,非常感谢给位帮助,哪怕给一点点提示
接受的子程序如下:
procedure TCommunication.TcpServerScanerAccept(Sender: TObject;
ClientSocket: TCustomIpClient);
var
s: string;
DataThread:TScanThread;
ClientThread: TClientSocketThread;
begin
DataThread:= TScanThread.Create(true);
DataThread.SetThreadEnvironment(fDataProcessIp,fDataProcess,self); ClientThread:=nil;
ClientThread:=ClientSocket.GetThreadObject;
if ClientThread<>nil then
begin
s:='';
s:=ClientThread.ClientSocket.Receiveln(ConstTerminateChar);
while s <> '' do
begin
DataThread.AddScanDataToList(s);
s := ClientThread.ClientSocket.Receiveln(ConstTerminateChar);
end; DataThread.Resume;
end;
end;
接受的子程序如下:
procedure TCommunication.TcpServerScanerAccept(Sender: TObject;
ClientSocket: TCustomIpClient);
var
s: string;
DataThread:TScanThread;
ClientThread: TClientSocketThread;
begin
DataThread:= TScanThread.Create(true);
DataThread.SetThreadEnvironment(fDataProcessIp,fDataProcess,self); ClientThread:=nil;
ClientThread:=ClientSocket.GetThreadObject;
if ClientThread<>nil then
begin
s:='';
s:=ClientThread.ClientSocket.Receiveln(ConstTerminateChar);
while s <> '' do
begin
DataThread.AddScanDataToList(s);
s := ClientThread.ClientSocket.Receiveln(ConstTerminateChar);
end; DataThread.Resume;
end;
end;
DataThread:TScanThread;为数据处理线程
DataThread.AddScanDataToList(s);是把接收到的数据包传入线程的一个List
之所以用此控件,并且使用Receiveln是因为我的服务器和客户端之间传送的是串,因为刚开始的时候系统设计用webservice,后来发现速度太慢,指标达不到实时系统要求才改用sock通讯的,原来的通讯协议没有改变,还是传送xml,这样为了避免手动组包就使用了这个控件。但是因为对此控件内部工作不是很熟悉,造成现在的问题望各位能帮帮忙,非常感谢
一般或者是使用TServerSocket,或者TIdTcpServer....尽管没用过TTcpServer...
你代码倒是有个明显错误,你不该在OnAccept的事件里面去传输数据..在这儿传数据..不阻塞才是怪事,呵呵.
再怎么着,也要在client对应线程里面传数据...如果可能,还是建议你使用TIdTcpServer...易用稳定可靠得多,能够避免很多人为使用错误造成的问题.
能说明白一些吗?ID的控件不具备我现在的需求,现在我在服务器和客户端之间传送的是串,而且使用现在控件可以避免组包,因为现在用的控件就自动组好了。传送串手工组包很不方便。
我分析过源码,它的WRITELN和READLN方法明显成熟于TTCPSERVER的实现。不管用什么SOCKET控件,它们都是在用SOCKET,
当使用多线程阻塞方式的SOCKET写服务器时,
一个客户端连接上来,就分配一个线程去传输它的数据。。
OnAccept是ACCEPT一个连接时候触发的,它的触发是在侦听线程,而你要传数据的
应该是用分配给客户端的那个线程。使用TTCPSERVER一般写法,同TSOCKETSERVER很类似,
在TTCPSERVER有ONGETTHREAD事件里创建你的线程对象,这个线程对象的类由你定义,
重载CLIENTEXECUTE方法实现。。嘿嘿。。这样麻烦易错的东西,我是没兴趣用。