2

我有一个 GPS 设备,它将安装在许多卡车上。我可以将设备配置为通过 gprs 向 IP 和端口发送数据语句“gps 数据,设备 ID”。我正在使用TcpListener类来读取服务器端的数据。

TcpListener server = null;
private void listen_data()
{
    Int32 port = controller_port;
    IPAddress localAddr = IPAddress.Parse(this_ip);
    server = new TcpListener(localAddr, port);
    server.Start();
    Byte[] bytes = new Byte[256];
    String data = null;
    while (true)
    {
        Console.Write("Waiting for a connection...-- ");
        TcpClient client = server.AcceptTcpClient();
        Console.Write("Connected!");
        data = null; int i;
        NetworkStream stream = client.GetStream();
        while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
        {
            data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
        }
    }
}

该方法正在侦听服务器 ip 和端口上的内容。

  1. 我想知道我是否将设备配置为在同一个端口上发送到服务器。我能够监听所有设备还是第一个连接的设备将是唯一的?

  2. 这种方法是从设备读取传入数据的最佳方法吗?

  3. 我是否需要为每个设备配置不同的端口并为每个设备端口创建一个新的监听线程?

  4. 有时我会遇到异常“请求通道在等待回复时超时”

非常感谢您的帮助。

4

2 回答 2

2

在您的代码中,您正在侦听所有设备,但只有在完成从第一个设备读取所有数据之后,您才会收到“请求通道在等待回复时超时”。您应该有不同的线程,每个线程处理一个tcpClient.

所以代码应该是这样的:

TcpListener server = null;
private void listen_data()
{
    Int32 port = controller_port;
    IPAddress localAddr = IPAddress.Parse(this_ip);
    server = new TcpListener(localAddr, port);
    server.Start();
    while (true)
    {
        Console.Write("Waiting for a connection...-- ");
        TcpClient client = server.AcceptTcpClient();
        Console.WriteLine("new client connected");
        ThreadPool.QueueUserWorkItem(new WaitCallback(HandleClient), client);//or use Task if 4.0 or new Thread...
    }
}

private void HandleClient(object tcpClient)
{
    TcpClient client = (TcpClient)tcpClient;
    Byte[] bytes = new Byte[256];
    String data = null;
    int i;

    NetworkStream stream = client.GetStream();
    while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
    {
        data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
    }

    Console.WriteLine(data);
}
于 2011-07-11T11:48:30.193 回答
0

1)两者。您应该能够侦听所有设备,但您的​​代码通常不能,因为侦听器线程正在等待来自较早连接的设备的流。

2) 可能不会。IIRC,NetworkStream.Read 当连接被对等设备关闭时返回 0。这是你的协议吗 - 即。设备连接,发送一些数据并断开连接?如果是这样,那将起作用,尽管速度很慢。无论如何,还有另一个问题。您应该将流中接收到的字节连接到数据,而不仅仅是替换它们 - Read() 我多次返回一次通信,甚至可能每次只有一个字节(不太可能,但允许使用 TCP 流)。您可以保留 rx 字节数。到目前为止并使用 'offset' 参数来执行此操作。

3)你只需要一个监听线程,即。调用 AcceptTcpClient() 的那个。此线程不应进行阻塞调用以从 AcceptTcpClient() 返回的套接字接收数据。为 AcceptTcpClient() 返回的每个“客户端”套接字创建/分配/解池/任何新的客户端-服务器线程来运行 Read() 循环,或者使用异步 IO。

4)您的单个侦听器/读取线程在等待 NetworkStream 时将对新连接无响应 - 其他设备将无法连接。侦听器应该快速返回 AcceptTcpClient(),而不是等待慢速网络/设备发送数据。

Rgds,马丁

于 2011-07-11T11:41:37.400 回答