indy tcp的即时通讯的问题

 
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连接,它会帮你分配相应的连接的
一句话:
    不用关心如何实现这么多的连接
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值