通过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();
}
}
}我正在努力解决的问题是如何促进SerialPort实例和线程之间的通信。
我不确定上面的代码是不是最好的方法,所以有没有人有其他的解决方案(越简单越好)?
发布于 2010-04-07 15:21:35
为什么要在这么低的级别(套接字)写?为什么不使用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设备的通信,这样您就可以轻松地完成请求-响应周期,而不会受到干扰。
这还允许您很好地(在等待句柄上)超时,以通知客户端当前没有可用的响应。
发布于 2020-10-17 02:53:50
你有socat,ser2net和其他程序,但我的经验非常糟糕……不能正常工作。我自己做的这个python小程序,可以派上用场。更新端口,波特率...然后使用任何tcp客户端。如果不想用作自动可执行脚本,请删除第一行
#!/usr/bin/python
import socket
import sys
import serial
#open serial port
ser = serial.Serial('/dev/ttyAMA0', 115200, timeout=0)
#create socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
#bond to the port. Don't use localhost to accept external connections
server_address = ('', 2105)
print('starting up on {} port {}'.format(*server_address))
sock.bind(server_address)
#listen
sock.listen(1)
#loop
while True:
#waits for a new connection
print('waiting for a connection')
connection, client_address = sock.accept()
try:
print('connection from', client_address)
#continously send from serial port to tcp and viceversa
connection.settimeout(0.1)
while True:
try:
data = connection.recv(16)
if data == '': break
ser.write(data)
except KeyboardInterrupt:
connection.close()
sys.exit()
except Exception as e:
pass
received_data = ser.read(ser.inWaiting())
connection.sendall(received_data)
except Exception as e:
print e
finally:
#clean up connection
connection.close()https://stackoverflow.com/questions/2590236
复制相似问题