- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我是 Indy 的新手。这是我第一次在这里发布问题。
我的项目必须以 60Hz 的频率向所有客户端发送数据。为此,我正在使用 TIdTCPServer
来监控保持事件状态。我的工具很旧,在 WinXP 上运行,使用 C++Builder 6 和 Indy 8。有一个潜在的超时问题,有没有人想过如何处理它?
这是我的代码:
服务器端
typedef struct
{
AnsiString PeerIP; //{ Cleint IP address }
AnsiString HostName; //{ Hostname }
int Id; // {Cleint ID}
} TClient;
// This is Multimedia timer callback function, on 60Hz
void CALLBACK mmTimerProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
DWORD T1, T2;
TfmMain *pMain = (TfmMain *)dwUser;
int Index;
double dT;
TClient *pClient;
if (pMain->IsClosing) return;
if (pMain->Shutdown)
{
return;
}
pMain->UpdateServer1Data();
TList *pList = pMain->IdTCPServer1->Threads->LockList();
try
{
for(int X = 0; X < pList->Count; X++)
{
if (!pMain->IsClosing)
{
TIdPeerThread *AThread = (TIdPeerThread *)pList->Items[X];
if(AThread != NULL)
{
pClient = (TClient *)AThread->Data;
try
{
if(!AThread->Connection->ClosedGracefully)
{
// Send data to ALL Clients
AThread->Connection->WriteBuffer(&pMain->Data2Client, sizeof(pMain->Data2Client), true);
}
}
catch(Exception &E)
{
if(!AThread->Stopped)
{
AThread->Stop();
AThread->Connection->Disconnect();
}
}
}
}
}
}
__finally
{
pMain->IdTCPServer1->Threads->UnlockList();
}
// Shutdown computer or close application
if(pMain->SimIos.Status.iSimStatus == 11)
{
pMain->Shutdown = true;
pMain->CloseApp();
}
}
void __fastcall TfmMain::IdTCPServer1Connect(TIdPeerThread *AThread)
{
TClient *pClient = NULL;
AnsiString ABuffer, text;
AnsiString PeerIP = AThread->Connection->Binding->PeerIP;
TDateTime TimeConnected = Now();
ABuffer = AThread->Connection->ReadLn();
if((ABuffer.Pos("TT") == 0) && (ABuffer.Pos("IG") == 0) && (ABuffer.Pos("RR") == 0))
{
text = AnsiString().sprintf("1>>> Unknown(%s) on %s connected illegal!...",
PeerIP, DateTimeToStr(TimeConnected));
WriteMsg(text);
AThread->Connection->Disconnect();
return;
}
if(ABuffer.Pos("IG") != 0)
{
pClient = new TClient;
pClient->PeerIP = PeerIP;
pClient->HostName = Clients[eIG];
pClient->Id = eIG;
AThread->Data = (TObject *)pClient;
AThread->FreeOnTerminate = true;
// Report client is on line
}
text = AnsiString().sprintf("1>>>%s(%s) on %s on line!...",
pClient->HostName, PeerIP, DateTimeToStr(TimeConnected));
WriteMsg(text);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::IdTCPServer1Disconnect(TIdPeerThread *AThread)
{
TClient *pClient = NULL;
AnsiString Msg;
if (IsClosing) return;
pClient = (TClient *)AThread->Data;
if(pClient->Id == 1)
{
// Report client is off line
Msg = AnsiString().sprintf("1>>>%s(%s) on %s off line...",
pClient->HostName, pClient->PeerIP, DateTimeToStr(Now()));
WriteMsg(Msg);
}
delete pClient;
AThread->Data = NULL;
AThread->Terminate();
try
{
IdTCPServer1->Threads->LockList()->Remove(AThread);
}
__finally
{
IdTCPServer1->Threads->UnlockList();
}
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::IdTCPServer1Execute(TIdPeerThread *AThread)
{
TClient *pClient;
if (!AThread->Terminated && !IsClosing)
{
pClient = (TClient *)AThread->Data;
if((pClient != NULL) && (pClient->Id != 0))
{
try
{
if(pClient->Id == 1)
{
// Report client still alive
}
}
catch(Exception &E)
{
if (!IsClosing)
{
if(!AThread->Stopped)
{
AThread->Stop();
AThread->Connection->Disconnect();
}
}
}
}
}
}
客户端
void __fastcall TSocketThread::Execute()
{
unsigned long ulCheckSum;
SIM_SVR1_ACK_STRUCT Ack2Svr;
SIM_SVR_DATA DataFromSvr;
int Counter;
memset(&DataFromSvr, 0, sizeof(DataFromSvr));
memset(&Ack2Svr, 0, sizeof(Ack2Svr));
Counter = 0;
// fetch and process commands until the connection or thread is terminated
while (!this->Terminated && FSocket->Connected())
{
try
{
// recieve data from server
FSocket->ReadBuffer(&DataFromSvr, sizeof(DataFromSvr));
// check CRC
ulCheckSum = CRC_32((unsigned char*)&DataFromSvr.SimData, sizeof(DataFromSvr.SimData));
if (ulCheckSum == DataFromSvr.uiCheckSum)
{
FSmIpcUtil->Writeto(&DataFromSvr.SimData, DATA_OFFSET, sizeof(DataFromSvr.SimData));
}
else
{
// counter to record error
Synchronize(UpdateCaption);
}
// read return from local SM
FSmIpcUtil->Readfrom(&Ack2Svr, ACK_OFFSET, sizeof(Ack2Svr));
FSocket->WriteBuffer(&Ack2Svr, sizeof(Ack2Svr));
if (DataFromSvr.SimData.SimIgTgt.Acdata.iSimStatus == 11)
{
Terminate();
FSocket->Disconnect();
PostMessage(Application->Handle, WM_SHUTDOWN, 0, 0);
Sleep(500);
}
}
catch (EIdException& E)
{
this->Terminate();
FSocket->Disconnect();
}
}
}
最佳答案
您的代码有几个问题。
多媒体计时器回调在允许执行的操作方面非常受限:
Applications should not call any system-defined functions from inside a callback function, except for
PostMessage
,timeGetSystemTime
,timeGetTime
,timeSetEvent
,timeKillEvent
,midiOutShortMsg
,midiOutLongMsg
, andOutputDebugString
.
如果传输速度很重要,则根本不要让计时器回调进行广播。将数据保存在安全的地方,然后让每个 TIdTCPServer
线程按自己的时间获取最新数据。这也使每个连接线程保持隔离,因此如果出现问题,一个连接不会影响任何其他连接。
不要将 TIdPeerThread::FreeOnTerminate
设置为 true,不要调用 TIdPeerThread::Stop()
,不要手动从 TIdTCPServer 中删除线程: :Threads
属性。您不拥有线程,TIdTCPServer
拥有线程,它会为您管理它们。如果你想停止一个给定的线程,你需要做的就是关闭线程的套接字。但是通过将所有发送逻辑移动到它所属的 OnExecute
中,您可以让 TIdTCPServer
处理任何错误并为您关闭套接字。
只有当 IG 客户端连接时,您的 OnConnect
事件处理程序才会设置 AThread->Data
,但是您的 OnConnect
和 OnDisconnect
处理程序在尝试访问 TClient
对象之前不检查该条件。
如果 IsClosing
为真,则您的 OnDisconnect
事件处理程序正在泄漏内存。它调用 Threads->UnlockList()
而不是先调用 Threads->LockList()
。在列表未被调用线程锁定时尝试解锁列表将导致错误和死锁。
尝试更像这样的东西:
struct TClient
{
AnsiString PeerIP; //{ Client IP address }
AnsiString HostName; //{ Hostname }
int Id; //{ Client ID }
};
void CALLBACK mmTimerProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
TfmMain *pMain = (TfmMain *)dwUser;
if (pMain->IsClosing || pMain->Shutdown) return;
pMain->UpdateServer1Data();
// make sure pMain->Data2Client is thread-safe...
// set a signal that Data2Client has been updated...
// Shutdown computer or close application
if (pMain->SimIos.Status.iSimStatus == 11)
{
pMain->Shutdown = true;
pMain->CloseApp();
}
}
void __fastcall TfmMain::IdTCPServer1Connect(TIdPeerThread *AThread)
{
TClient *pClient;
AnsiString ABuffer, text;
AnsiString PeerIP = AThread->Connection->Binding->PeerIP;
TDateTime TimeConnected = Now();
ABuffer = AThread->Connection->ReadLn();
if ((ABuffer.Pos("TT") == 0) && (ABuffer.Pos("IG") == 0) && (ABuffer.Pos("RR") == 0))
{
text = AnsiString().sprintf("1>>> Unknown(%s) on %s connected illegal!...", PeerIP.c_str(), DateTimeToStr(TimeConnected).c_str());
WriteMsg(text);
AThread->Connection->Disconnect();
return;
}
pClient = new TClient;
pClient->PeerIP = PeerIP;
if (ABuffer.Pos("IG") != 0)
{
pClient->HostName = Clients[eIG];
pClient->Id = eIG;
}
else
pClient->Id = 0;
AThread->Data = (TObject *)pClient;
// Report client is on line
text = AnsiString().sprintf("1>>>%s(%s) on %s on line!...", pClient->HostName.c_str(), PeerIP.c_str(), DateTimeToStr(TimeConnected).c_str());
WriteMsg(text);
}
void __fastcall TfmMain::IdTCPServer1Disconnect(TIdPeerThread *AThread)
{
TClient *pClient = (TClient *)AThread->Data;
AnsiString Msg;
AThread->Data = NULL;
if (pClient)
{
// Report client is off line
Msg = AnsiString().sprintf("1>>>%s(%s) on %s off line...",
pClient->HostName.c_str(), pClient->PeerIP.c_str(), DateTimeToStr(Now()).c_str());
WriteMsg(Msg);
delete pClient;
}
}
void __fastcall TfmMain::IdTCPServer1Execute(TIdPeerThread *AThread)
{
TClient *pClient;
if (IsClosing) return;
// make sure pMain->Data2Client is thread-safe...
if (Data2Client has been updated since last event)
{
AThread->Connection->WriteBuffer(&pMain->Data2Client, sizeof(pMain->Data2Client), true);
}
pClient = (TClient *)AThread->Data;
// Report client still alive
}
关于delphi - TIdTCPServer 如何在 60Hz 计时器中向所有客户端多播?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40519135/
我想在一些计算机之间建立点对点连接,这样用户就可以在没有外部服务器的情况下聊天和交换文件。我的第一个想法如下: 我在服务器上创建了一个中央 ServerSocket,所有应用程序都可以连接到该服务器。
我正在 Unity 中构建多人游戏。为此,我必须将一些值从客户端发送到两个或多个通过服务器连接的客户端。我想将其构建为服务器真实游戏。客户端将使用 Android,他们的数据将通过服务器同步(可能是一
练习 C 网络编程:我正在编写一个简单的 TCP 客户端-服务器应用程序,它应该将消息(在每个客户端的单独线程中)作为字符串从服务器发送到客户端并在客户端(稍后将成为控制台商店应用程序)。我首先发送消
我使用证书身份验证设置了 AWS Client VPN。我正在为客户端-客户端访问系统进行设置,基本上如 this AWS scenario/example 中所述.一切正常,如果我知道他们的 IP
我正在开发一个小型客户端1/客户端2、服务器(线程)TCP 游戏。在尝试处理延迟问题时,我意识到我的 transmitState() 中存在缺陷。它强制将不必要的信息传递到通讯流中,从而造成迟缓,将汽
来自文档:Configurable token lifetimes in Azure Active Directory (Public Preview) 它提到“ secret 客户端”,刷新 tok
Apollo 客户端开发工具无法连接到我的应用程序。我已在 ApolloClient 构造函数中将 connectToDevTools 传递为 true,但没有任何 react 。我也试过this p
我想在 Pod 内使用 Fabric8 kubernetes 客户端 (java)。如何获取部署集群的 kubernetes 客户端? 我可以使用该集群的 kubeconfig 文件获取任何集群的配置
我正在阅读 the security issue with Log4j我了解此产品受此漏洞影响。但是 Oracle 客户端 11.2 和 12 是否受此问题影响? 我找不到这些产品是否使用任何 Log
Eureka 服务器设置 pom.xml 1.8 Hoxton.SR1 org.springframework.cloud spring
我有一个点对点(客户端/服务器)设置(通过本地 LAN),它使用 Netty,一个 Java 网络框架。我使用原始 TCP/IP(例如,没有 HTTP)进行通信和传输。现在,根据要求,我们希望转向 T
上一篇已经实现了ModbusTcp服务器和8个主要的功能码,只是还没有实现错误处理功能。 但是在测试客户端时却发现了上一篇的一个错误,那就是写数据成功,服务器不需要响应。 接下来要做的就是实现Modb
有没有办法将二维十六进制代码数组转换为 png 图像? 数组看起来像这样(只是更大) [ [ '#FF0000', '#00FF00' ], [ '#0000FF'
我是套接字编程的新手。每次我运行客户端程序时,它都会说“无法连接到服务器”。谁能告诉我我在哪里犯了错误。任何帮助将不胜感激。 这是client.c #include #include #inclu
我们在UNIX环境下制作了简单的client.c和server.c程序。我们使用它来传输一个简单的文本文件,首先打开它,然后读取它并使用 open、read 和 send 系统调用发送;在客户端,我接
当我的程序来自 my previous question正在响应客户端,它应该发送加密消息。 当客户端连接时,它会发送一条类似“YourMessage”的消息。现在我想做的是,当客户端连接时,应该以某
我正在使用 C 和 putty 编写客户端/服务器程序。两个 c 文件位于同一系统上。 我目前在向客户端写回其正在使用的框架以及打印我的框架时遇到问题。它打印出 3 0 9 8,但随后开始打印 134
我正在使用 C 中的 select() 制作一个模拟快餐或其他任何东西的客户端服务器。 我有客户随机点 1-5 种“食物”。服务器每 30 秒决定一次。所有客户最喜欢的食物是什么?他为那些客户提供服务
对于单机游戏,基本的游戏循环是(来源:维基百科) while( user doesn't exit ) check for user input run AI move enemies
1、CentOS安装TortoiseSVN 复制代码 代码如下: yum install -y subversion 2、SVN客户端命令
我是一名优秀的程序员,十分优秀!