IDTcpServer丢数据?请高手指教&……

啥都得学呀 2009-08-28 02:15:45
我刚刚做了个测试

用INDY里的TCPSERVER和 TCPCLIENT


执行的功能是,CLINET循环500次连接,每次连接随便发送一个简单的字符串。SERVER端,只负责记录下来这些数据,记录成功,返回1,记录失败,返回2。

当我开一个CLIENT的时候,每次都完全都能记录下来500条数据。而且完全都成功的。即使循环100次,也没问题。


但是,当我用2个CLIENT,差不多一起点循环按钮的时候,问题就出现了。如果2个客户端分别循环500次的话,差不多丢了100以上的数据,更可恨的事,返回的结果居然都是成功。当然,极少的情况下也会出现失败。但少的可怜……

我想知道,怎么会丢数据了呢??


附带我接受的时候的代码 IdTCPServerExecute(AContext: TIdContext);ReceText := copy(s, 5, length(s));
TIdSync.SynchronizeMethod(ExecuteCommand);
if OpResult then AContext.Connection.Socket.Write('1' + #13#10) OpResult 是操作结果
else AContext.Connection.Socket.Write('2' + #13#10);

{这里是同步方法}
procedure TFormIndex.ExecuteCommand;
var MainData: string;
begin
{执行命令}
OpResult := ValiKey(ReceText);{这里判断的是字符串是否合法}
if not OpResult then exit;

MainData := copy(ReceText, pos('|', ReceText) + 1, length(ReceText));

OpResult := REWRITETXT(ExtractFilePath(Paramstr(0)) + 'SysLog.txt', MainData);{这里执行把数据写入TXT文本}
end;


{这里是写入TXT文本}
function REWRITETXT(FILEPATH: string; VALUES: string): BOOLEAN;
var
FileHandle: integer;
txtFile: TextFile;
begin
try
if not FileExists(FILEPATH) then
begin
FileHandle := FileCreate(FILEPATH);
FileClose(FileHandle);
end;
AssignFile(txtFile, FILEPATH);
Append(txtFile);
Writeln(txtFile, VALUES);
CloseFile(txtFile);
RESULT := TRUE;
except
RESULT := FALSE;
end;
end;

...全文
201 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
sanguomi 2009-08-29
  • 打赏
  • 举报
回复
一般来说,VCL可视控件都不是线程安全的,非可视的基本都是.
利用消息队列进行VCL可视控件的同步,所以一般VCL可视组件要用
synchronize同步
TCriticalSection 只是对全局的数据比如变量进行保护,不能保护VCL类

俩者应用是不同的,
啥都得学呀 2009-08-29
  • 打赏
  • 举报
回复
那么,问题如何根本上解决?没有人正面回答和解答我的难题么?
sanguomi 2009-08-29
  • 打赏
  • 举报
回复
Synchronize()只是将该线程的代码放到主线程中运行,并非线程同步。
啥都得学呀 2009-08-29
  • 打赏
  • 举报
回复
如果不同步,写文本就会出错。因为多个线程,在并发的时候操作一个文件,那就肯定也出错了
啥都得学呀 2009-08-29
  • 打赏
  • 举报
回复
我刚刚测试过了。如果全部转成局部变量,情况确实好一些。那么,我现在开始怀疑,那同步过程到底有什么意义了!!


另外,测试结果表明,当多个客户端同时循环的连接发送中,服务器端,在写文本的时候,会出错。也就是,大家一起写一个文本,当某个并发点诞生的时候,写入是失败的。
那么,如何回避这个问题呢?
啥都得学呀 2009-08-29
  • 打赏
  • 举报
回复

[Quote=引用 4 楼 jadeluo 的回复:]
对于多个Client在Server端的线程来说, 你的ReceText和OpResult都是个全局变量, 会出现多个线程同时读取这些变量的可能, 导致程序逻辑异常。
[/Quote]

同步过程中,也会出现这个问题?还望赐教一二!难道,这里不采用全局变量而用局部变量,而抛弃同步TIdSync.SynchronizeMethod
jadeluo 2009-08-29
  • 打赏
  • 举报
回复
对于多个Client在Server端的线程来说, 你的ReceText和OpResult都是个全局变量, 会出现多个线程同时读取这些变量的可能, 导致程序逻辑异常。
啥都得学呀 2009-08-29
  • 打赏
  • 举报
回复
居然没人回复?!难道都遇到这个问题没解决?
啥都得学呀 2009-08-29
  • 打赏
  • 举报
回复
问题解决了如下!

先声明一个TRTLCriticalSection类型的全局变量

var
MyCs:TRTLCriticalSection;

在程序开始或建立线程之前,初始化

InitializeCriticalSection(MyCs);//初始化临界区

在程序结束或所有线程结束后,删除它

DeleteCriticalSection(MyCs);//删除临界界

再在线程中要同步的地方加入

EnterCriticalSection(MyCs); //进入临界区
try
//程序代码
finally
LeaveCriticalSection(MyCs); //离开临界区
end;



另外在提一个问题,我唯一没弄明白的问题。

TIdSync.SynchronizeMethod 或者 Synchronize 到底什么时候用我看INDY的DEMO里,就没用。但是有人开发的DEMO里就强调了这一点。我现在很茫然。

我个人猜想:如果使用主线程中的控件,如TEXTBOX等可视的控件,就用Synchronize 。反之。就可以不用!

个人感觉还是很茫然。烦劳高手们指教!
shuihan20e 2009-08-29
  • 打赏
  • 举报
回复
TCriticalSection
SuperTitan001 2009-08-29
  • 打赏
  • 举报
回复
搜索delphi 临界区就可以了
临界区和线程有关,与indy, IDTCPSERVER没有关系
啥都得学呀 2009-08-29
  • 打赏
  • 举报
回复
搜索了一下,DELPHI INDY IDTCPSERVER 的临界区的帖子和技术文档 都没有!
啥都得学呀 2009-08-29
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 shuihan20e 的回复:]
可以借助临界区
[/Quote]

边界区?没用过。有例子么?
shuihan20e 2009-08-29
  • 打赏
  • 举报
回复
可以借助临界区
啥都得学呀 2009-08-28
  • 打赏
  • 举报
回复
无疑中发现的。我就想测试下并发……

开了4个客户端,每个客户端都是1-500次连接,每次连接发一条数据就关。

结果,发现记录下来的数据少了2、300条数据。都不知道丢啥地方去了。更可气的是,返回的结果都是成功的。

如果单独开一个客户端,1对1的发包(发多少次都不会出问题,都毫无遗漏的记录下来),就不会出问题。我找了半天问题。也不知道咋回事%……
shuihan20e 2009-08-28
  • 打赏
  • 举报
回复
先SF,再仔细看

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧