http://community.csdn.net/Expert/topic/4543/4543923.xml?temp=.7700312
INDY自代的例子看了一下,以前用过TServerSocket做过这方面的东西!
TCommBlock = record
// the Communication Block used in both parts (Server+Client)
Command: TCommand;
MyUserName, // the sender of the message
Msg, // the message itself
ReceiverName: string[100]; // name of receiver
end;
这是他里面的协议的定义,我这里需要的类似的MSN那种 ,先登录,然后是简单的信息通讯,客户大概100左右!我觉得INDY应该能承受的住!这个协议如何能定议的比较灵活,为以后扩展打下基础!希望大家讨论一下!或是有这方面的经验,交流一下!
问题已找到:
问题还是出现在TThreadList上面,
procedure TServerFrmMain.Button1Click(Sender: TObject);
var
i: integer;
ActClient: PClient;
RecThread: TIdPeerThread;
NewCommBlock: TCommBlock;
begin
try
for i := 0 to Clients.LockList.Count - 1 do//这句,每次循环一个对象,都会EnterCriticalSection 一次,这样就会导致程序不可以继续运行,
改为with Clients.LockList DO 这样就会保证只执行一次EnterCriticalSection !
begin
NewcommBlock.Command := cMessage;
NewcommBlock.MyUserName := 'system';
NewcommBlock.Msg := 'system test';
NewcommBlock.ReceiverName := '';
ActClient := Clients.LockList.Items[i];//此处改为ActClient := Items[i];
RecThread := ActClient.Thread;
finally//这里
Clients.UnlockList;
end;
RecThread.Connection.WriteBuffer(NewCommBlock, SizeOf(NewCommBlock), True);
end;
end;
通过查看TThreadlist的源码,然后自定义一个TMYThreadList类,为跟踪使用!这个问题其实大家很容易犯的,如果不看源码或跟踪一下,不容易找到答案的,希望与大家分享一下!
IdTcpCilent/Server编程中,AThread.Data指的是什么
这是留给你用的,一般都用来指向用作纪录对方连接的信息的对象或者结构
用来保存自己定义的类或其他数据,连接中断时自动释放。
这个Data其实就是代表连接对方的东西,
比如一个文件服务器,对话开始后,设定一个初始目录,然后接受客户的命令,客户发送cd xxx时,服务器必须记住客户在对话期间的当前目录,所以要持有一个对象或者数据结构来记录这些信息,
tpeer = class
ip: string;
currDir: string;
end;
tserver = class
private
fTCPServ: TIdTCPServer;
fClients: TThreadList;
procedure
procedure onConnect(aThread: TIdPeerThread);
procedure OnDisconnect(aThread: TIdPeerThread)
procedure OnCDCommand(aSender: TIdCommand);
...
procedure TServer.OnConnect(aThread: TIdPeerThread);
var
client: tpeer;
begin
//当连接开始时,创建客户对象
client := tpeer.create();
client.ip := ...;
client.cd := default_directory;
...
aThread.Data := client;
//如果有必要,记录将这个对象添加到当前活动对话当中
//那么, fclientList则反映了当前活动的连接,以及各个连接的相关信息
fClients.LockList();
try
fClients.add(client);
finally
fClients.unlocklist();
end;
end;
procedure TServer.OnCDCommand(aSender: TIdCommand);
var
client: tpeer;
targetDir: string;
begin
//处理CD命令
//取得持有的peer对象
client := tpeer(aSender.thread.data);
targetDir := MyParseParam(aSender.Params);
//执行cd命令,并更新current directory
client.currDir := ChangeDir(client.currDir + targetDir);
MyReplyOk(aSender);
end;
procedure TServer.OnDisconnect(aThread: TIdPeerThread);
begin
//如果先前纪录了peer,现在要把它从列表中去掉
fClients.LockList();
try
fClients.remove(aThread.Data);
finally
fClients.Unlocklist();
end;
//连接断开了,这个时候要释放先前创建的peer对象
tpeer(aThread.Data).Free();
aThread.Data := nil;
end;
简单的用法就是这样
如何记录客户端的IP
有一段代码,看看:
type
PClient =^TClient;
TClient = Record
DNS:String[20];
IP: String[20];
Thread:Pointer;
end;
var
Clients:TThreadList;
procedure TInforServer.IdTCPServer1Connect(AThread: TIdPeerThread);
var
NewClient:PClient;
begin
New(NewClient);
NewClient^.IP:=
AThread.Connection.Socket.Binding.PeerIP;
NewClient^.Thread:=AThread;
AThread.Data:=TObject(NewClient);
try
Clients.LockList.Add(NewClient);
finally
Clients.UnlockList;
end;
end;
procedure TInforServer.IdTCPServer1Disconnect(AThread: TIdPeerThread);
var
ActClient:PClient;
begin
ActClient:=PClient(AThread.Data);
try
Clients.LockList.Remove(ActClient);
finally
Clients.UnlockList;
end;
dispose(ActClient);
AThread.Data:=nil;
end;
IdTCPServer如何段开和客户端的连接
1、请问IdTCPServer如何段开和客户端的连接,现在有我写了一个SERVER端和一Client端程序,当Client先段开与SERVER的连接,SERVER再停掉服务没有问题,但是当Client没有段开连接而SERVER直接关闭服务就会报异常,我想在关闭SERVER前先关掉所有客户端的连接,试了很长时间都没有成功,请问怎么解决。SERVER用的是IdTCPServer,Client用的是IdTCPClient控件。
2、还有一个小问题,IdTCPServer好象本身就是多线程的,我是不是就不用在为每个连接写个线程了,我看到一些文章提到要用线程池,它是做什么用的,怎么用,为什么用,不用行不行,(第一个问题是最最急的,请先帮我解决第一个,多谢多谢。)。
IdTCPClient在什么地方接收,我总不能单独写个线程一直再那里READLN()来等待服务器的呼叫
**************************************
呵呵,你说对了,IdTCPClient就是这样接收的。
其实之所以出错,是线程不能正常退出的原因。而INDY是阻塞的,服务器端的readln是线程里的代码,又一直停在那里,服务器直接退出的话,线程不能正常退出,所以出错。
所以,在server的线程里接收,要先判断线程是不是退出或连接是否成功,即
while not terminate or IdTCPClient.Connected=ture do
begin
//接收代码
end;
TIdTCPServer+线程池,但是线程池怎么用啊
TIdTCPServer+线程池,但是线程池怎么用啊??客户端请求的时候,服务怎么开1000个连接的
直接将 TIdTHreadMgrPool与TIdTCPServer的THREADMGR属性关联即可
致于你说的1000个连接,如果同时有这么多的客户端与SERVER连接,它会帮你分配相应的连接的
一句话:
不用关心如何实现这么多的连接