请指点一下这个关于IdTCPServer多个客户端连入的问题

caike 2005-03-23 08:20:29
如果我想服务器可以同时连入多个客户端,那服务器端这个多线程该如何编写呢?我不知道如何从IdTCPServer这个控件下手,还请指点,谢谢!
...全文
850 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
caike 2005-03-28
  • 打赏
  • 举报
回复
gzmhero(hihihi)大侠,您批评的对!
我看了INDY的英文帮助,单看IdTCPServer和IdTCPClient这二个组件的帮助,看得很糊涂!文件的打开当时我也想了一下,因为是文件打开为读fmpopenread,所以觉得这样打开文件应该不会错。我总是想在这二个组件上了。我是第一次用网络组件开发,所以有许多地方不懂,还得请您和其他大侠指点,代码我其实也不想知道,我只想知道解决的思路,但以前没开发过网络这方面程序,思路上很糊涂!
很感谢您这样全力的帮助!谢谢!分数奉上!
gzmhero 2005-03-25
  • 打赏
  • 举报
回复
sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead);
"其他程序正在使用该文件..."

////////////////
文件权限出了问题,其他程序正打开这个文件,所以不能读出。不是程序逻辑的问题。
看一下是不是你的其他程序正在使用这个文件。
caike 2005-03-25
  • 打赏
  • 举报
回复
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
sFile:TFileStream;
sv:TIdStreamVCL;
begin
sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead);
AContext.Connection.IOHandler.WriteLn(IntToStr(sFile.Size));
sv:=TIdStreamVCL.Create(sFile,true);
AContext.Connection.IOHandler.Write(sv,sFile.Size);
FreeAndNil(sFile);
end;

gzmhero(hihihi) 大侠,还是不行,服务器端在下面这条语句报错,
sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead);
"其他程序正在使用该文件..."

caiso 2005-03-25
  • 打赏
  • 举报
回复
顶一下
gzmhero 2005-03-25
  • 打赏
  • 举报
回复
还是帮人帮到底吧。

服务端再改一下,主要是文件打开的模式:

procedure TForm1.FormShow(Sender: TObject);
begin
IdTcpServer1.Active:=true;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
IdTcpServer1.Active:=false;
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
sFile:TFileStream;
sv:TIdStreamVCL;
begin
sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead+fmShareDenyWrite);
sv:=TIdStreamVCL.Create(sFile,true);
AContext.Connection.IOHandler.WriteLn(IntToStr(sFile.Size));
AContext.Connection.IOHandler.Write(sv,sFile.Size);
sFile.Free;
end;
gzmhero 2005-03-25
  • 打赏
  • 举报
回复
给你的代码只是一个思路,解决一些问题,不可能提供给你一个完整的代码呀。

你应该自己试着去解决一些问题。
caike 2005-03-25
  • 打赏
  • 举报
回复
但如果要传送多个文件,这种方法似乎不行。
gzmhero 2005-03-25
  • 打赏
  • 举报
回复
是服务端的OnExecute事件里面造成,当函数里面出现了异常,连接关闭。
还是文件操作的问题。
服务端改成这样:

var
sFile:TFileStream;
sv:TIdStreamVCL;

procedure TForm1.FormShow(Sender: TObject);
begin
IdTcpServer1.Active:=true;
sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead);
sv:=TIdStreamVCL.Create(sFile,true);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
IdTcpServer1.Active:=false;
sFile.Free;
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
begin
sFile.Position:=0;
AContext.Connection.IOHandler.WriteLn(IntToStr(sFile.Size));
AContext.Connection.IOHandler.Write(sv,sFile.Size);
end;
caike 2005-03-25
  • 打赏
  • 举报
回复
大侠,还是不行,我就用您上面的那段代码进行测试,还是不能进行多个客户端传输,当第二个连接到服务器时,在服务器上可以显示到第二个客户端的地址,但
在第二个客户端就会报错:Connection Closed Gracefully.
第一个客户端传送正常
gzmhero 2005-03-24
  • 打赏
  • 举报
回复
cjf1009(农民程序员)

///////////////////////////
不会覆盖,形成不同的bpl,你可以选择使用indy9或者indy10。
caike 2005-03-24
  • 打赏
  • 举报
回复
我在试试
caike 2005-03-24
  • 打赏
  • 举报
回复
但我在程序中遇到过这种情况,如果服务器端不发送数据,而客户端readln,则客户端就一直停在readln上面了。
gzmhero 2005-03-24
  • 打赏
  • 举报
回复
应该不会一直停留在readln里,会有超时的异常。循环读,应该能读到Ready的。
caike 2005-03-24
  • 打赏
  • 举报
回复
大侠,有一问题,客户端在线程中循环读?如果服务器端不发送数据,则客户端就会一直停留在readln这条语句上,就像是死机了。并且后面服务器端发送了ready给客户端,客户端也没反应了。
是不是客户端也要一直发送数据呢?
cjf1009 2005-03-24
  • 打赏
  • 举报
回复
如果当时客户端不在线呢?不是错过了更新的机会?
我觉得这类似于升级程序,得客户端主动,就得涉及本地和服务器文件版本号等问题了。

如果只是象你说的那中情况,能保证服务器发‘Ready’的时候客户端肯定在,那就是 gzmhero(hihihi) 所说了
gzmhero 2005-03-24
  • 打赏
  • 举报
回复
对,放到线程里,在读到Ready后。
caike 2005-03-24
  • 打赏
  • 举报
回复
那客户端第2步接收文件也是在同一个线程里面吗?
gzmhero 2005-03-24
  • 打赏
  • 举报
回复
这样的逻辑看看行不行:
服务端:
1、IdTcpServer打开。
2、备份数据。
3、备份完成后,对连接的客户端发送命令,自己定义.譬如'Ready'
4、发送文件。

客户端:
1、在一个线程里循环。
1)连接服务端。
2)读服务端数据,循环读,直到读到Ready
2、接收文件。
caike 2005-03-24
  • 打赏
  • 举报
回复
gzmhero(hihihi)大侠,有个这样问题,不知您是否能指点一下:
我想先将数据备份了,再进行传送,我在服务器端设置了一个自动备份的时间,IdTCPServer是一启动程序时我就将其设置Actived;在客户端设置了接收时间,当时间一到,则客户端启动IdTCPClient.Connect,但我发现备份时间过长了,超过了客户端设置的接收时间,就会造成客户端接收数据不正确!

但如果是将服务器端的备份时间设置的比客户端的接收时间提前,那是可以,但是我不能掌握备份时间要多久,所以我觉得这样还是不行。

如果我在备份后才启动IdTCPServer,但客户端的接收时间就不能确定了,这样我觉得也不行!

我现在是这样做的:在服务器onexecute这个事件中设置了一个循环,并加了一个变量用来判断是否备份完成,如果备份完成就发送‘OK’字符串到客户端,并且在这个循环里不停的发送‘NO’到客户端;同样,在客户端我也设置了一个循环,在循环里面不停的接收服务器端发过来的字符并进行判断,如果是OK则退出循环,进入传送数据状态,反之,继续接收。但这样有时还是会出些问题。

我想做到备份数据完后,客户端才开始接收数据,但备份时间不能确定有多久。
对上面这个问题,不知是否还有其他的解决办法?不知您是否能指点一下?谢谢!
cjf1009 2005-03-24
  • 打赏
  • 举报
回复
ok,谢谢 gzmhero(hihihi)
加载更多回复(10)

1,593

社区成员

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

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