2010-04-07 82 views
1

通过TCP共享COM端口到多个客户端的简单设计模式是什么?通过TCP共享COM端口

例如,本地GPS设备可以实时向远程主机传输坐标。

所以我需要一个程序,将打开串口并接受像多个TCP连接:

class Program 
{ 
    public static void Main(string[] args) 
    { 
     SerialPort sp = new SerialPort("COM4", 19200, Parity.None, 8, StopBits.One); 

     Socket srv = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     srv.Bind(new IPEndPoint(IPAddress.Any, 8000)); 
     srv.Listen(20); 

     while (true) 
     { 
      Socket soc = srv.Accept(); 
      new Connection(soc); 
     } 
    } 
} 

然后,我会需要一个类来处理连接的客户机之间的通信,使他们都可以看到数据并保持同步,以便客户指令顺序接收:

class Connection 
{ 
    static object lck = new object(); 
    static List<Connection> cons = new List<Connection>(); 

    public Socket socket; 
    public StreamReader reader; 
    public StreamWriter writer; 

    public Connection(Socket soc) 
    { 
     this.socket = soc; 
     this.reader = new StreamReader(new NetworkStream(soc, false)); 
     this.writer = new StreamWriter(new NetworkStream(soc, true)); 
     new Thread(ClientLoop).Start(); 
    } 

    void ClientLoop() 
    { 
     lock (lck) 
     { 
      connections.Add(this); 
     } 
     while (true) 
     { 
      lock (lck) 
      { 
       string line = reader.ReadLine(); 
       if (String.IsNullOrEmpty(line)) 
        break; 

       foreach (Connection con in cons) 
        con.writer.WriteLine(line); 
      } 
     } 
     lock (lck) 
     { 
      cons.Remove(this); 
      socket.Close(); 
     } 
    } 
} 

我奋力化解的问题是如何促进一个串口实例和线程之间的通信。

我不确定上面的代码是否是最好的方式,所以有人有另一种解决方案(越简单越好)?

回答

1

为什么在这样的低级别(套接字)写?为什么不使用WCF作为客户端和服务器之间的通信,并提供一个更清洁,强类型的接口,而不是原始访问GPS设备?

像这样的设备通常是独立于客户端呼入的最佳管理方式 - 也就是说,您有自己的单独线程与GPS设备进行对话,以适当的时间间隔轮询它并使用当前位置填充共享数据结构 - 客户端进行服务调用并提供来自共享数据结构的数据。对于有时不可靠的设备连接,所有的错误处理和恢复都由GPS线程处理,客户端不需要每个人都参与到这种混乱中。他们可以进行非阻塞呼叫以获取状态更新,而这些更新可能包含状态“不可用”状态,而GPS线程正在疯狂尝试重新建立通信。

因此,我会创建一个服务,抽象处理这个特定设备的细节,并为客户提供一个干净的接口。例如,它可能提供像GetPosition()这样的服务,它返回一些像“GeoCoordinate”这样的类。这样,如果您需要支持其他位置感应设备,您可以添加它们而不需要对客户端代码进行任何更改。

    GPS <--Serial--> Server <--WCF--> Clients 

我有数百个不同的设备,在许多串行端口和其他半可靠的连接,这是我使用的方法的通信系统。见http://blog.abodit.com

-----按你使用TELNET附加要求:也许是这样的:

创建处理与设备本身的所有通信的线程。

创建一个封装单个WorkItem的类 - 要发送的内容,响应和WaitHandle。

使用队列来排队来自客户端的请求。每个客户端在WaitHandle上等待其响应准备就绪。

让单个通信线程从该队列中拉出工作项目,将它们发送到GPS设备,获取响应,将响应存储在WorkItem中(或设置失败标志),然后设置等待句柄WorkItem已完成。

如果请求速度超过GPS可处理的速度,请添加代码,以便它可以返回缓存的值,用于在上次成功请求到设备的小时间窗口内发送请求。

实际上,您现在向所有客户端展示了一个虚拟GPS设备,但在内部您将序列化其所有请求(在队列中)并管理与单个线程上的GPS设备的通信,以便您可以执行请求 - 响应轻松循环而不受干扰。

这也允许您很好地(在等待句柄上)超时以通知客户端当前没有响应。

+0

感谢您使用WCF的建议。但是,我忽略了在我的问题中提到我想使用telnet客户端进行连接,并且这将是双向通信,而不仅仅是接收。 我很好奇看到您的实施,但我无法在您的博客上找到任何代码 - 您是否有任何示例?我仍然喜欢在套接字级别工作,但是我在如何与不同线程沟通方面停滞不前。 – 2010-04-08 04:13:00

+0

博客上没有代码,对不起,这是一个庞大的系统。我会在我的答案中增加一些更多的建议。 – 2010-04-08 05:08:13

+0

感谢您的更新和体系结构建议 - 使用队列是一种有效的解决方案。我还发现了以下链接,显示如何将COM端口链接到单个TCP连接:http://www.javiervalcarce.eu/wiki/Access_to_serial_port_from_Internet – 2010-04-09 05:11:25