如何解决TIdTCPServer 共享串口
最近我更改了一个程序,它充当 TCP 服务器以帮助共享连接到设备的串行端口上的流量。多个客户端连接并且应该可以访问串行端口并同时操作。
应用程序是使用 C++Builder 构建的,在服务器中使用 TIdTCPServer
,在客户端应用程序中使用 TIdTCPClient
。
多个客户端需要连接并发送命令到串口。串口在向它发送命令后会立即响应,根据它所连接的设备的协议。
还有一个后台线程偶尔访问串行端口并更新服务器内存中保存的数据的内存缓存。用于从串行端口发送和接收的命令上有一个互斥锁,因此可以从 TIdTcpServer
的 OnExecute
事件和后台线程访问它们。
我很难让 TIdTCPServer
的 OnExecute
事件在不重叠的情况下正常工作。
如果 OnExecute
事件能够完全执行而没有来自另一个客户端的另一个请求导致重叠,那就太好了。
这是 OnExecute
的 TIdTCPServer
事件处理程序:
void __fastcall TfrmMain::IServerExecute(TIdContext *AContext)
{
int i;
int Len;
TIdBytes TRB,TSB;
unsigned char ARB[BUFFERLENGTH];
int NumbSent,NumbReceived;
// Read the command from the client. Send the length first then the actual data.
Len = AContext->Connection->Socket->ReadLongInt();
AContext->Connection->Socket->ReadBytes(TRB,Len,false);
memset(ARB,BUFFERLENGTH);
for(i=0;i<Len;i++) AOB[i]=TRB[i];
NumbSent=Len;
// Now send it out to the Serial port
ProcessSerialMessage(AOB,ARB,&NumbReceived,false);
sending=false;
TSB.Length=NumbReceived;
for(i=0;i<TSB.Length;i++) TSB[i]=ARB[i];
AContext->Connection->Socket->Write(TSB.Length);
AContext->Connection->Socket->Write(TSB);
return;
}
这是通过串口发送数据的例程:
int ProcessSerialMessage(unsigned char *SendBuf,int NumbSBytes,unsigned char *ReceiveBuf,int *NumbRBytes,bool CalledFromThread)
{
// MMUtex is a global TMutex Object
// Mutex required to help with the background thread trying to update memory cache.
MMutex->Acquire();
// Ok now send the data out over the serial port and receive it.
// These routines are standard serial port I/O routines and aren't explained here.
rawsend(SendBuf,NumbSBytes);
rawreceive(ReceiveBuf,NumbRBytes);
RetValue=*NumbRBytes;
MMutex->Release();
return(RetValue);
}
解决方法
top_n_terms <- text %>%
tokens(remove_numbers = TRUE,remove_punct = TRUE,remove_symbols = TRUE) %>%
tokens_ngrams(n = 1:3) %>%
dfm() %>%
dfm_remove(stopwords("en")) %>%
topfeatures(n = 3000) %>%
sparsity()
是一个多线程组件。每个连接的客户端都在自己独立的线程中运行。 TIdTCPServer
事件在这些线程中运行。因此,您有责任通过序列化对任何共享资源的访问来确保您的 OnExecute
代码是线程安全的。
您在 OnExecute
内部使用了互斥锁,因此您正在序列化对串行端口的访问(假设您的其他后台线程也进入相同的互斥锁)。所以这应该没问题(尽管我建议使用 ProcessSerialMessage()
块或本地 RAII 样式类保护互斥锁锁定/解锁,以确保互斥锁即使抛出异常也能正确解锁)。
但是,我在这段代码中看到的一个主要问题是您的 try..__finally
(和 AOB
)变量没有声明为 sending
的局部变量,这意味着它必须是一个跨线程访问的共享变量(更新:您已在评论中确认:“[AOB 是] 全局声明。”)。但是,它不受多个线程并发访问的保护,这意味着多个客户端可以在发送到串行端口时自由覆盖彼此的入站数据。
您正在将串行端口的响应读入局部变量,然后使用它们发送回发出请求的客户端。所以这段代码没有并发问题。
我建议将您的 IServerExecute()
和 TRB
数组直接传递给 TSB
。您必须将字节从一个数组复制到另一个数组的 2 个循环并不是真正必要的,因此您可以完全消除此代码中的 ProcessSerialMessage()
和 AOB
变量。这可能足以解决您的问题。
试试这个:
ARB
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。