我认为这里的问题是它会冻结列表,并且在调用unlockList之前不会处理其他客户端请求.那么它不会损害服务器的性能吗?锁定列表并在连接之间进行迭代以转发每条消息(因为这是在信使中经常发生的事情).有没有更好的方法来做到这一点?
我使用的是Indy 10和Delphi 7
广播代码:
Var tmpList: TList; i: Integer;BegintmpList := IDServer.Contexts.LockList;For i := 0 to tmpList.Count Do Begin TIDContext(tmpList[i]).Connection.socket.WriteLn('broadcast message');End;IDServer.Contexts.UnlockList;
转发邮件的代码:
Var tmpList: TList; i: Integer;Begin tmpList := IDServer.Contexts.LockList; For i := 0 to tmpList.Count Do Begin If TIDContext(tmpList[i]).Connection.socket.Tag = IDReceiver Then TIDContext(tmpList[i]).Connection.socket.WriteLn('Message'); End; IDServer.Contexts.UnlockList;解决方法 是的,您必须遍历上下文列表才能向多个客户端广播消息.但是,您没有(也不应该)从循环内部执行实际写入.一,正如您已经注意到的那样,通过保持列表锁定一段时间可以影响服务器性能.二,它不是线程安全的.如果您的循环将数据写入连接而另一个线程同时写入同一连接,则这两个写入将相互重叠并破坏与该客户端的通信.
我通常做的是实现每个客户端的出站队列,使用TIDContext.Data属性或TIDServerContext后代来保存实际队列.当您需要从该客户端的OnExecute事件外部向客户端发送数据时,请将数据放入该客户端的队列中.然后,客户端的OnExecute事件可以在安全的情况下将队列的内容发送到客户端.
例如:
type TMyContext = class(TIDServerContext) public Tag: Integer; Queue: TIDThreadSafeStringList; ... constructor Create(AConnection: TIDTCPConnection; AYarn: TIDYarn; AList: TThreadList = nil); overrIDe; destructor Destroy; overrIDe; end;constructor TMyContext.Create(AConnection: TIDTCPConnection; AYarn: TIDYarn; AList: TThreadList = nil);begin inherited; Queue := TIDThreadSafeStringList.Create;end;destructor TMyContext.Destroy;begin Queue.Free; inherited;end;
.
procedure TForm1.FormCreate(Sender: TObject);begin IDServer.ContextClass := TMyContext;end;procedure TForm1.IDServerConnect(AContext: TIDContext);begin TMyContext(AContext).Queue.Clear; TMyContext(AContext).Tag := ...end;procedure TForm1.IDServerdisconnect(AContext: TIDContext);begin TMyContext(AContext).Queue.Clear;end;procedure TForm1.IDServerExecute(AContext: TIDContext);var Queue: TStringList; tmpList: TStringList;begin ... tmpList := nil; try Queue := TMyContext(AContext).Queue.Lock; try if Queue.Count > 0 then begin tmpList := TStringList.Create; tmpList.Assign(Queue); Queue.Clear; end; finally TMyContext(AContext).Queue.Unlock; end; if tmpList <> nil then AContext.Connection.IOHandler.Write(tmpList); finally tmpList.Free; end; ...end;
.
var tmpList: TList; i: Integer;begin tmpList := IDServer.Contexts.LockList; try for i := 0 to tmpList.Count-1 do TMyContext(tmpList[i]).Queue.Add('broadcast message'); finally IDServer.Contexts.UnlockList; end;end;
.
var tmpList: TList; i: Integer;begin tmpList := IDServer.Contexts.LockList; try for i := 0 to tmpList.Count-1 do begin if TMyContext(tmpList[i]).Tag = IDReceiver then TMyContext(tmpList[i]).Queue.Add('Message'); end; finally IDServer.Contexts.UnlockList; end;end;总结
以上是内存溢出为你收集整理的delphi – Indy 10 TCP服务器全部内容,希望文章能够帮你解决delphi – Indy 10 TCP服务器所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)