- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想创建一个 TCPserver 并根据需要向客户端发送/接收消息,而不是 TCPserver 的 OnExecute 事件。
发送/接收消息没有问题;我确实喜欢这样:
procedure TFormMain.SendMessage(IP, Msg: string);
var
I: Integer;
begin
with TCPServer.Contexts.LockList do
try
for I := 0 to Count-1 do
if TIdContext(Items[I]).Connection.Socket.Binding.PeerIP = IP then
begin
TIdContext(Items[I]).Connection.IOHandler.WriteBuffer(Msg[1], Length(Msg));
// and/or Read
Break;
end;
finally
TCPServer.Contexts.UnlockList;
end;
end;
注1:如果我不使用OnExecute,程序会在客户端连接时引发异常。
注 2:如果我不执行任何操作就使用 OnExecute,CPU 使用率将达到 %100
注 3:我没有机会更改 TCP 客户端。
那我该怎么办?
最佳答案
TIdTCPServer
需要默认分配的 OnExecute
事件处理程序。为了解决这个问题,您必须从 TIdTCPServer
派生一个新类并重写其虚拟 CheckOkToBeActive()
方法,并且还应该重写虚拟 DoExecute()
调用 Sleep()
。否则,只需分配一个事件处理程序并让它调用 Sleep()
。
但这并不是 TIdTCPServer
的有效使用。更好的设计是不要直接从 SendMessage()
方法内部将出站数据写入客户端。这不仅容易出错(您没有从 WriteBuffer()
捕获异常)并在写入期间阻止 SendMessage()
,而且它还会序列化您的通信(客户端 2 无法接收数据,直到客户端 1 首先接收数据)。更有效的设计是为每个客户端提供自己的线程安全出站队列,然后让 SendMessage()
根据需要将数据放入每个客户端的队列中。然后,您可以使用 OnExecute
事件检查每个客户端的队列并进行实际写入。这样,SendMessage()
就不会再被阻塞,更不容易出错,并且可以并行写入客户端(就像它们应该的那样)。
尝试这样的事情:
uses
..., IdThreadSafe;
type
TMyContext = class(TIdServerContext)
private
FQueue: TIdThreadSafeStringList;
FEvent: TEvent;
public
constructor Create(AConnection: TIdTCPConnection; AYarn: TIdYarn; AList: TThreadList = nil); override;
destructor Destroy; override;
procedure AddMsgToQueue(const Msg: String);
function GetQueuedMsgs: TStrings;
end;
constructor TMyContext.Create(AConnection: TIdTCPConnection; AYarn: TIdYarn; AList: TThreadList = nil);
begin
inherited;
FQueue := TIdThreadSafeStringList.Create;
FEvent := TEvent.Create(nil, True, False, '');
end;
destructor TMyContext.Destroy;
begin
FQueue.Free;
FEvent.Free;
inherited;
end;
procedure TMyContext.AddMsgToQueue(const Msg: String);
begin
with FQueue.Lock do
try
Add(Msg);
FEvent.SetEvent;
finally
FQueue.Unlock;
end;
end;
function TMyContext.GetQueuedMsgs: TStrings;
var
List: TStringList;
begin
Result := nil;
if FEvent.WaitFor(1000) <> wrSignaled then Exit;
List := FQueue.Lock;
try
if List.Count > 0 then
begin
Result := TStringList.Create;
try
Result.Assign(List);
List.Clear;
except
Result.Free;
raise;
end;
end;
FEvent.ResetEvent;
finally
FQueue.Unlock;
end;
end;
procedure TFormMain.FormCreate(Sender: TObject);
begin
TCPServer.ContextClass := TMyContext;
end;
procedure TFormMain.TCPServerExecute(AContext: TIdContext);
var
List: TStrings;
I: Integer;
begin
List := TMyContext(AContext).GetQueuedMsgs;
if List = nil then Exit;
try
for I := 0 to List.Count-1 do
AContext.Connection.IOHandler.Write(List[I]);
finally
List.Free;
end;
end;
procedure TFormMain.SendMessage(const IP, Msg: string);
var
I: Integer;
begin
with TCPServer.Contexts.LockList do
try
for I := 0 to Count-1 do
begin
with TMyContext(Items[I]) do
begin
if Binding.PeerIP = IP then
begin
AddMsgToQueue(Msg);
Break;
end;
end;
end;
finally
TCPServer.Contexts.UnlockList;
end;
end;
关于delphi - 没有 OnExecute 事件的 TCPserver,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9324723/
如何在 Ruby 中使用 TcpServer.new(0) 找到由 Windows 分配给 TcpServer 的端口 最佳答案 您可以使用 addr 获取它: tcp_server = TCPSer
我已经阅读了 Ruby 文档,但我并没有真正理解这两个对象之间的区别。 TCPServer.new(端口) 和 TCPServer.open("X.X.X.X", 端口) 我所知道的是 .new 仅响
我不得不为工作中的一个项目编写一个 TCP 服务器,我在谷歌上搜索了如何编写。我有一个 MSDN回答并设法让它工作,但我不知道如何让数据能够来回接收。 socket 的连接时间最多不会超过 30 秒(
import SocketServer import sys from Queue import * import threading class CustomTCPServer(SocketServ
python 2.7.2 window 7 32 位 让我以我对网络编程相当陌生作为这个问题的序言。我使用 python 的内置 SocketServer 创建了一个简单的服务器和客户端 Socket
我有一个正在编码的应用程序,用于通过 tcpsocket 将日志记录信息发送到服务器,并有一个监视器客户端连接到服务器以查看日志记录数据。到目前为止,我能够进入将信息发送到服务器的阶段,但是我需要一些
我正在尝试编写一个 c# 服务器/客户端,它将同时通过 TCP 相互发送字节数组。我正在努力思考如何实现这一目标。我见过的所有示例都在等待消息,然后发送响应。我需要同时进行交流。 我是否需要为服务器和
也许我把我的套接字编程方式搞混了,但像这样的东西不应该工作吗? srv = TCPServer.open(3333) client = srv.accept data = "" while (tmp
我目前仅使用标准库在 ruby 中实现一个简单的发布/订阅系统,客户端可以在其中订阅消息主题或将消息发布到主题,这些消息将发送给所有订阅者。我只使用标准的 TCPServer 并假设所有消息都在使
int main() { int sock, connected, bytes_recieved , true = 1; char send_data [1024] , recv_data[1
我正在尝试使用 jacoco 代理远程获取覆盖数据,并使用 Reset=true 重置服务器上的执行信息; 服务器上的jacoco java代理: JAVA_OPTIONS="${JAVA_OPTIO
我试图通过客户端的 GET 请求从 SocketServer 模块关闭 TCPServer,该请求在窗口关闭时发出,但是以下代码无法启动关闭: def show_webgl(data): im
我正在编写一个简单的 python3 网络服务器。我已经尝试了各种教程,并且都运行良好。尽管如此,还是有一点我不明白。 在一个教程中,他们使用 HTTPServer 如下: server = HTTP
目前我有一个 c# tcpclient 和一个 c++ tcpserver,但我只能从服务器端的流中读取字符,因此所有数据都将转换为字符。由于c++ char是一个有符号的8位整数,而c#客户端发送的
我一直在玩弄 Python 的 SocketServer: #!/usr/bin/python import SocketServer class EchoHandler(SocketServer.B
我正在创建一个仅在 Windows 操作系统上运行的客户端-服务器应用程序,每个 Windows 用户将一次连接到服务器。局域网使用DHCP,所以IP不固定。 我需要将字符串消息从 IdTCPServ
我尝试在客户端发送长度小于 255 的数据。 我尝试使用此协议(protocol)发送数据: Lenghth+String Byte+string sample : string = ABCD sen
我正在使用 Python 的 SocketServer.ThreadingTCPServer。现在我想知道在某个时刻连接了多少个客户端。 如何解决? 最佳答案 SocketServer.Threadi
我想创建一个 TCPserver 并根据需要向客户端发送/接收消息,而不是 TCPserver 的 OnExecute 事件。 发送/接收消息没有问题;我确实喜欢这样: procedure TForm
我需要有关 TCPServer 和 TcpClient 问题的帮助。我正在使用 Delphi XE2 和 Indy 10.5。 我根据一个流行的屏幕捕获程序制作了服务器和客户端程序: ScreenTh
我是一名优秀的程序员,十分优秀!