чтение сообщений с устройства через gprs - PullRequest
2 голосов
/ 11 июля 2011

У меня есть устройство GPS, которое будет установлено во многих грузовиках. Я могу настроить устройство для отправки оператора данных «данные GPS, идентификатор устройства» через GPRS на IP и порт. Я использую 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. иногда я сталкиваюсь с исключениями "истекло время ожидания канала запроса в ожидании ответа"

заранее большое спасибо за вашу помощь.

Ответы [ 2 ]

2 голосов
/ 11 июля 2011

В вашем коде вы слушаете все устройства, но только после того, как закончите читать все данные с первого устройства, поэтому вы получаете "канал запроса истек во время ожидания ответа". У вас должны быть разные потоки, каждый из которых обрабатывает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);
}
0 голосов
/ 11 июля 2011

1) Оба. Вы должны иметь возможность прослушивать все устройства, но вы часто не можете с вашим кодом, потому что поток слушателя связан с ожиданием потока от устройства, которое подключалось ранее.

2) Вероятно, нет. IIRC, NetworkStream.Read возвращает 0, когда соединение закрыто одноранговым устройством. Это твой протокол - т.е. устройство подключается, отправляет некоторые данные и отключается? Если так, то это будет работать, хотя и медленно. Во всяком случае, есть другая проблема. Вы должны объединять байты, полученные в вашем потоке, с данными, а не просто заменять их - Read (), я возвращаюсь несколько раз за одно сообщение, возможно, даже с одним байтом каждый раз (маловероятно, но разрешено для потоков TCP). Вы можете сохранить количество байтов RX. до сих пор и использовать параметр «смещение», чтобы сделать это.

3) Вам нужен только один поток прослушивания, т.е. тот, который вызывает AcceptTcpClient (). Этот поток не должен выполнять блокирующие вызовы для получения данных из сокета, возвращаемого AcceptTcpClient (). Либо создайте / выделите / удалите / какой-либо новый поток клиент-сервер для запуска цикла Read () для каждого сокета 'client', возвращаемого AcceptTcpClient (), или используйте асинхронный ввод-вывод.

4) Ваш единственный поток прослушивания / чтения не будет отвечать на новые подключения, пока он ожидает NetworkStream - другие устройства не смогут подключиться. Слушатель должен быстро вернуться к AcceptTcpClient () и не ждать медленных сетей / устройств для отправки данных.

Rgds, Martin

...