我维护的VB6应用程序需要做的是以下内容。
发送请求
等待回复。
我尝试使用WinSock和Winsock替换,但他们都依赖于各种Windows应用程序中固有的消息循环。我不太了解Winsock API如何在VB6(或任何其他语言)中实现上述算法。
我的应用程序是VB6 CAD / CAM软件,可通过专用以太网控制金属切割机。该软件已经维护了20年,我们为不同类型的运动控制器开发了几个驱动程序。迄今为止,这些运动控制器的API由
组成这些控制器中的一些通过以太网工作,但直到现在我从未必须直接与端口交互。我使用公司提供的库来处理事情。它们以我上面提到的方式工作,并且如果在某个定义的时间内没有响应,则抛出超时错误。
Winsock的问题是我必须插入DoEvents才能得到响应。这会对我们在VB6应用程序中处理多任务的方式造成严重破坏。像CSocketMaster这样的替代品使用了子类化,这也会对我们的多任务处理造成严重破坏。
所以有关如何使用Winsock API或第三方dll的任何帮助都可以完成我需要做的事情,如上所述。我不会问我是否还没有看到其他运动控制做我想做的事。
答案 0 :(得分:2)
在github上查看VbAsyncSocket repo以获取纯VB6异步套接字实现(使用WSAAsyncSelect
API为套接字发布事件通知)。
与其名称相反,类支持同步操作的SyncSendArray
和SyncReceiveArray
方法 - 没有DoEvents
但{{1} }}第
在同一个repo中有一个方便的cWinSockRequest
贡献类,它与操作系统中的Timeout
对象非常相似。如果您有使用JSON / XML(通常是基于http / https的RESTful服务)的经验,通过普通的tcp / udp套接字访问服务/设备,那么这个帮助程序类将非常适合您。
另一种选择是使用cTlsClient
贡献的类,可以通过tcp连接到主机/设备(这里没有udp)并提供WinHttpRequest
/ ReadText
和WriteText
/ ReadArray
(同步)方法。这里的另一个好处是,如果需要,该类支持普通的未加密套接字和SSL加密通道。
我们正在使用这些类来(同步)从我们的LOB应用程序访问ESP / POS打印机。大多数POS打印机也提供串行(USB到COM)链接,因此我们抽象了我们的访问w /连接器类 - SyncWaitForEvent
通过异步套接字和WaitForMultipleObjects
重叠WriteArray
/ ReadFile
API(哦,具有讽刺意味)
答案 1 :(得分:1)
我认为很少适合做网络 同步,但这不是传统意义上的网络。 这是从PC到控制器的电线。这就像一个字符串 两罐之间。在这种情况下,使用大型旧程序,最多 适当的方法是最好的方法,也是最简单的方法 维修。的< / end2cents>
如果VB6 + Winsock没有为您服务,那么在.NET中编写它并将其构建为VB6程序的COM可视DLL将符合要求。
以下示例将帮助您入门。如果你做的不仅仅是偶尔打电话给它,它会很慢,因为它打开并关闭每次通话的连接。它应该很容易扩展,以允许重新使用开放式连接来进行PC和控制器之间的来回通信。请注意,不要造成内存泄漏!
/// <summary>
/// Sends a message to the specified host:port, and waits for a response
/// </summary>
public string SendAndReceive(string host, int port, string messageToSend, int millisecondTimeout)
{
try
{
using (var client = new TcpClient())
{
client.SendTimeout = client.ReceiveTimeout = millisecondTimeout;
// Perform connection
client.Connect(host, port);
if (client.Connected)
{
using (var stream = client.GetStream())
{
// Convert the message to a byte array
var toSend = Encoding.ASCII.GetBytes(messageToSend);
// Send the message
stream.Write(toSend, 0, toSend.Length);
// Get a response
var response = new byte[client.ReceiveBufferSize];
stream.Read(response, 0, client.ReceiveBufferSize);
return Encoding.ASCII.GetString(retVal);
}
}
else
{
return null;
}
}
}
catch
{
return null;
}
}
答案 2 :(得分:1)
事实证明,答案涉及实施艾伦的建议。
具体问题是在一台机器控制中涉及的两台设备之间进行通信。执行运动控制的设备充当服务器,而提供运动数据的PC则是客户端。
以太网用于代替专用总线接口或RS-232/422串行接口。在广泛的互联网上提供数据所涉及的许多因素都不是一个因素。该网络由驻留在固定IP的已知设备组成,可以监听特定端口。
与做出其他动作控制的人交谈后。事实证明,客户的逻辑非常简单。
在服务器端,我们很幸运,我们控制了运动控制器上运行的软件。因此,通信环路的设计尽可能快。一个关键点是将所有数据保持在512字节以下,因此它全部包含在一个数据包中。他们还非常谨慎地建立了通信处理程序和数据结构,因此它可以在几十微秒内发出响应。
另一点是,在专用客户端和服务器的应用程序中,UDP优先于TCP作为操作系统,特别是Windows习惯于意外关闭空闲TCP连接。
因为客户端软件正在慢慢过渡到.NET框架,这是实现Allen的想法的另一个因素。 @wqw讨论的图书馆工作得很好。
答案 3 :(得分:0)
您的问题是您错误地使用了Winsock控件。这可能源于您的交互模型中的缺陷。
不要发送并等待&#34;因为这样的阻挡是你的大错。没有&#34;等待&#34;无论如何,除非你认为坐在一个嗡嗡声循环中等待。
而是发送您的请求并退出该事件处理程序。您的所有代码都包含在事件处理程序中,以及它的工作原理。然后,当引发DataArrival事件时,将新到达的片段附加到流缓冲区,然后扫描汇编的流以获得完整的响应。然后继续处理响应。
使用您在发送后启用的Timer控件处理超时。组装完成的响应后,禁用Timer。如果间隔过去并且提升了Timer事件,那么请在那里进行错误处理。
你似乎有一个特别繁琐的协议,所以你不应该做任何其他事情。例如,您可以在处理完整响应后清除流缓冲区,因为无论如何都不会留下任何其他内容。
忘掉&#34;多任务&#34;并避免像他们那样的瘟疫之类的DoEvents()调用。
这是非常简单的东西。