请指点一下这个关于IdTCPServer多个客户端连入的问题 如果我想服务器可以同时连入多个客户端,那服务器端这个多线程该如何编写呢?我不知道如何从IdTCPServer这个控件下手,还请指点,谢谢! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 不用多线程,IdTcpServer自己会处理,你只要在相应的事件里写就行了。OnConnect,OnExecute.procedure TForm1.Button1Click(Sender: TObject);begin IdTCPServer1.Active:=true;end;procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);begin Memo1.Lines.Add('connect');end;procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);var sFile:TFileStream;begin sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead); AThread.Connection.WriteLn(IntToStr(sFile.Size)); FreeAndNil(sFile); AThread.Connection.WriteFile('e:\fmLogin.pas'); end; IdTcpServer的每个连接是一个TIdPeerThread,放在列表Threads: TThreadList;中, pt:TIdPeerThread pt:=idTcpServer.Threads.LockList.Items[i];pt.Connection.WriteBuffer(...); 大侠,在indy10里面IdTCPserver1Execute是这种格式:IdTCPServer1Execute(AContext: TIdContext);我没有找到和Thread有关的属性 procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);var sFile:TFileStream;begin sFile:=TFileStream.Create('e:\aa.doc',FmopenRead); AContext.Connection.IOHandler.WriteLn(IntToStr(sFile.Size)); FreeAndNil(sFile); AContext.Connection.IOHandler.WriteFile('e:\aa.doc');end; 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;客户端:procedure TForm1.Button1Click(Sender: TObject);var FileSize:integer; sFile:TFileStream; sv:TIdStreamVCL;begin Try IdTCPClient1.Connect; except showmessage('连接失败!'); exit; end; FileSize:=StrToInt(IdTCPClient1.IOHandler.ReadLn); sFile:=TFileStream.Create('e:\bb.pas',fmCreate); sv:=TIdStreamVCL.Create(sFile,true); While FileSize>4096 do begin IdTCPClient1.IOHandler.ReadStream(sv,4096); inc(FileSize,-4096); end; IdTCPClient1.IOHandler.ReadStream(sv,FileSize); sFile.Free;end; 本身一个IdTcpServer就可以多个Client连接的,不要你写什么多线程的。 最近都混在socket这块,常听gzmhero大侠讲解受益甚深啊~~gzmhero,谢谢!!!鞠躬 indy10还没有体验过,不知道从哪里下载,装上之后会不会覆盖d7自带的版本? cjf1009(农民程序员) ///////////////////////////不会覆盖,形成不同的bpl,你可以选择使用indy9或者indy10。 gzmhero(hihihi)大侠,有个这样问题,不知您是否能指点一下:我想先将数据备份了,再进行传送,我在服务器端设置了一个自动备份的时间,IdTCPServer是一启动程序时我就将其设置Actived;在客户端设置了接收时间,当时间一到,则客户端启动IdTCPClient.Connect,但我发现备份时间过长了,超过了客户端设置的接收时间,就会造成客户端接收数据不正确!但如果是将服务器端的备份时间设置的比客户端的接收时间提前,那是可以,但是我不能掌握备份时间要多久,所以我觉得这样还是不行。如果我在备份后才启动IdTCPServer,但客户端的接收时间就不能确定了,这样我觉得也不行!我现在是这样做的:在服务器onexecute这个事件中设置了一个循环,并加了一个变量用来判断是否备份完成,如果备份完成就发送‘OK’字符串到客户端,并且在这个循环里不停的发送‘NO’到客户端;同样,在客户端我也设置了一个循环,在循环里面不停的接收服务器端发过来的字符并进行判断,如果是OK则退出循环,进入传送数据状态,反之,继续接收。但这样有时还是会出些问题。我想做到备份数据完后,客户端才开始接收数据,但备份时间不能确定有多久。对上面这个问题,不知是否还有其他的解决办法?不知您是否能指点一下?谢谢! 这样的逻辑看看行不行:服务端:1、IdTcpServer打开。2、备份数据。3、备份完成后,对连接的客户端发送命令,自己定义.譬如'Ready'4、发送文件。客户端:1、在一个线程里循环。 1)连接服务端。 2)读服务端数据,循环读,直到读到Ready2、接收文件。 对,放到线程里,在读到Ready后。 如果当时客户端不在线呢?不是错过了更新的机会?我觉得这类似于升级程序,得客户端主动,就得涉及本地和服务器文件版本号等问题了。如果只是象你说的那中情况,能保证服务器发‘Ready’的时候客户端肯定在,那就是 gzmhero(hihihi) 所说了 大侠,有一问题,客户端在线程中循环读?如果服务器端不发送数据,则客户端就会一直停留在readln这条语句上,就像是死机了。并且后面服务器端发送了ready给客户端,客户端也没反应了。是不是客户端也要一直发送数据呢? 应该不会一直停留在readln里,会有超时的异常。循环读,应该能读到Ready的。 但我在程序中遇到过这种情况,如果服务器端不发送数据,而客户端readln,则客户端就一直停在readln上面了。 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);"其他程序正在使用该文件..." sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead);"其他程序正在使用该文件..."////////////////文件权限出了问题,其他程序正打开这个文件,所以不能读出。不是程序逻辑的问题。看一下是不是你的其他程序正在使用这个文件。 大侠,还是不行,我就用您上面的那段代码进行测试,还是不能进行多个客户端传输,当第二个连接到服务器时,在服务器上可以显示到第二个客户端的地址,但在第二个客户端就会报错:Connection Closed Gracefully.第一个客户端传送正常 是服务端的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; 还是帮人帮到底吧。服务端再改一下,主要是文件打开的模式: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(hihihi)大侠,您批评的对!我看了INDY的英文帮助,单看IdTCPServer和IdTCPClient这二个组件的帮助,看得很糊涂!文件的打开当时我也想了一下,因为是文件打开为读fmpopenread,所以觉得这样打开文件应该不会错。我总是想在这二个组件上了。我是第一次用网络组件开发,所以有许多地方不懂,还得请您和其他大侠指点,代码我其实也不想知道,我只想知道解决的思路,但以前没开发过网络这方面程序,思路上很糊涂!很感谢您这样全力的帮助!谢谢!分数奉上! 如何使用tbitmap在form上进行作图 请帮个忙,谢谢!在线等 用到TaskEntry 类,用use 声明哪个模块单块 急 D中有没有类似ISNULL这样的函数,在线等 请问怎么修改fastreport的默认图标? 谁那里有李维的《Borland传奇》这本书? 很想拜读 关于rave请问我怎么才能用程序代码手工增加一个page? Delphi SWF SDK的使用 关于程序员考试的问题? 按ctrl+空格时 它说:"List Index out of bounds(0)" “专家评审意见书”,请有经验的同志帮忙解释一下。欢迎参加讨论,希望能给大家以借鉴。 回报回报,问个问题先!~~~~
OnConnect,OnExecute.procedure TForm1.Button1Click(Sender: TObject);
begin
IdTCPServer1.Active:=true;
end;procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
Memo1.Lines.Add('connect');
end;procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var
sFile:TFileStream;
begin
sFile:=TFileStream.Create('e:\fmLogin.pas',FmopenRead);
AThread.Connection.WriteLn(IntToStr(sFile.Size));
FreeAndNil(sFile);
AThread.Connection.WriteFile('e:\fmLogin.pas');
end;
pt.Connection.WriteBuffer(...);
IdTCPServer1Execute(AContext: TIdContext);
我没有找到和Thread有关的属性
var
sFile:TFileStream;
begin
sFile:=TFileStream.Create('e:\aa.doc',FmopenRead);
AContext.Connection.IOHandler.WriteLn(IntToStr(sFile.Size));
FreeAndNil(sFile);
AContext.Connection.IOHandler.WriteFile('e:\aa.doc');
end;
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;客户端:procedure TForm1.Button1Click(Sender: TObject);
var
FileSize:integer;
sFile:TFileStream;
sv:TIdStreamVCL;
begin
Try
IdTCPClient1.Connect;
except
showmessage('连接失败!');
exit;
end; FileSize:=StrToInt(IdTCPClient1.IOHandler.ReadLn);
sFile:=TFileStream.Create('e:\bb.pas',fmCreate);
sv:=TIdStreamVCL.Create(sFile,true); While FileSize>4096 do
begin
IdTCPClient1.IOHandler.ReadStream(sv,4096);
inc(FileSize,-4096);
end;
IdTCPClient1.IOHandler.ReadStream(sv,FileSize);
sFile.Free;
end;
gzmhero,谢谢!!!鞠躬
不会覆盖,形成不同的bpl,你可以选择使用indy9或者indy10。
我想先将数据备份了,再进行传送,我在服务器端设置了一个自动备份的时间,IdTCPServer是一启动程序时我就将其设置Actived;在客户端设置了接收时间,当时间一到,则客户端启动IdTCPClient.Connect,但我发现备份时间过长了,超过了客户端设置的接收时间,就会造成客户端接收数据不正确!但如果是将服务器端的备份时间设置的比客户端的接收时间提前,那是可以,但是我不能掌握备份时间要多久,所以我觉得这样还是不行。如果我在备份后才启动IdTCPServer,但客户端的接收时间就不能确定了,这样我觉得也不行!我现在是这样做的:在服务器onexecute这个事件中设置了一个循环,并加了一个变量用来判断是否备份完成,如果备份完成就发送‘OK’字符串到客户端,并且在这个循环里不停的发送‘NO’到客户端;同样,在客户端我也设置了一个循环,在循环里面不停的接收服务器端发过来的字符并进行判断,如果是OK则退出循环,进入传送数据状态,反之,继续接收。但这样有时还是会出些问题。我想做到备份数据完后,客户端才开始接收数据,但备份时间不能确定有多久。
对上面这个问题,不知是否还有其他的解决办法?不知您是否能指点一下?谢谢!
服务端:
1、IdTcpServer打开。
2、备份数据。
3、备份完成后,对连接的客户端发送命令,自己定义.譬如'Ready'
4、发送文件。客户端:
1、在一个线程里循环。
1)连接服务端。
2)读服务端数据,循环读,直到读到Ready
2、接收文件。
我觉得这类似于升级程序,得客户端主动,就得涉及本地和服务器文件版本号等问题了。如果只是象你说的那中情况,能保证服务器发‘Ready’的时候客户端肯定在,那就是 gzmhero(hihihi) 所说了
是不是客户端也要一直发送数据呢?
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);
"其他程序正在使用该文件..."
"其他程序正在使用该文件..."////////////////
文件权限出了问题,其他程序正打开这个文件,所以不能读出。不是程序逻辑的问题。
看一下是不是你的其他程序正在使用这个文件。
在第二个客户端就会报错:Connection Closed Gracefully.
第一个客户端传送正常
还是文件操作的问题。
服务端改成这样: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;
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;
我看了INDY的英文帮助,单看IdTCPServer和IdTCPClient这二个组件的帮助,看得很糊涂!文件的打开当时我也想了一下,因为是文件打开为读fmpopenread,所以觉得这样打开文件应该不会错。我总是想在这二个组件上了。我是第一次用网络组件开发,所以有许多地方不懂,还得请您和其他大侠指点,代码我其实也不想知道,我只想知道解决的思路,但以前没开发过网络这方面程序,思路上很糊涂!
很感谢您这样全力的帮助!谢谢!分数奉上!