Ошибка асинхронного чтения из NetworkStream

Я сделал приложение для связи с IP-камерой. Это настроено для установления соединения по предопределенному адресу. И TCP Listener работает на этом адресе и принимает соединение с камеры. Когда камера подключается, я отправляю команду для получения потока MJpeg с камеры, и камера начинает отправлять поток в ответ на команду.

Я использую асинхронный метод для чтения потока из сокета. Но через какое-то время мое приложение зависает при чтении данных из сетевого потока.

Я использую этот код для чтения данных из сетевого потока, и мне нужно написать несколько сообщений на экране, чтобы получить статус подключения камеры.

    private void ReadData()
    {
        try
        {
            string msg = "Reading Data... client connected " + _camClient.Connected.ToString() +
                         "... netStream Readable " +
                         _netStream.CanRead.ToString();
            Console.WriteLine(msg);

            _callback = new AsyncCallback(GetData);
            _buffer = new byte[Buffersize];
            _async = _netStream.BeginRead(_buffer, 0, Buffersize, _callback, null);
        }
        catch (Exception ex) { Console.WriteLine("ReadData: " + ex.Message); }
    }

    private void GetData(IAsyncResult result)
    {
        try
        {
            int read = _netStream.EndRead(result);
            if (read > 0)
            {
                _data = new byte[read];
                Array.Copy(_buffer, 0, _data, 0, read);
                ProcessData();
            }
            ReadData();
        }
        catch (Exception ex) { Console.WriteLine("GetData: " + ex.Message); }
    }

person Shafqat Ali    schedule 15.11.2011    source источник
comment
Какое последнее сообщение написано, когда оно застревает?   -  person Marc Gravell    schedule 15.11.2011
comment
Я вижу последнее сообщение: "Чтение данных ... клиент подключен верно ... netStream Readable true". После этого сообщения приложение зависает.   -  person Shafqat Ali    schedule 16.11.2011


Ответы (1)


Во-первых, асинхронные методы в сетевых потоках хорошо известны тем, что теряют данные или никогда не возвращают данные! В вашем случае это может быть вызов ProcessData блокируется.

Что вам следует сделать, так это создать новый фоновый поток с блокирующим слушателем (не асинхронным), а затем использовать новый поток для чтения данных, пока слушатель продолжает прослушивать. У меня есть пример.

private static Socket s_chatListener;
public static void Listen(IPAddress LocalIPAddress, int Port)
    {
            IPEndPoint ipend = new IPEndPoint(LocalIPAddress, Port);
            s_chatListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            s_chatListener.Bind(ipend);
            s_chatListener.Listen(10);


            while (true)
            {
                Socket handler = s_chatListener.Accept();

                ParameterizedThreadStart pst = new ParameterizedThreadStart(loadMessageFromSocket);
                Thread t = new Thread(pst);
                t.Start(handler);


            }
    }


 private static  void loadMessageFromSocket(object socket)
    {
        Socket handler = (Socket)socket;
        string data = "";
        while (true)
        {
            byte[] butes = new byte[1024];
            int rec = handler.Receive(butes);

            data += ASCIIEncoding.ASCII.GetString(butes);

            if (data.IndexOf("\0") > -1)
                break;
        }

        handler.Shutdown(SocketShutdown.Both);
        handler.Close();


        Console.Write(data);
    }

Теперь просто вызовите метод Listen из нового потока в основной форме или в классе вызывающего. Надеюсь это поможет.

person James Jenkins    schedule 16.11.2011
comment
Привет, Джеймс Дженкинс! В нашем сценарии нашим клиентом является ip-камера, поэтому мы получаем поток в ответ на нашу команду, отправленную на камеру, и камера начинает бесконечно отправлять поток Mjpeg. Итак, как я могу использовать этот код в нашем сценарии. - person Shafqat Ali; 17.11.2011
comment
Просто не используйте Async. Запустите новый поток, отправьте команду на IP-камеру, а затем прочитайте поток, вы можете использовать StreamReader. Затем, когда у вас есть изображения, установите событие, чтобы проинформировать вызывающего абонента. - person James Jenkins; 17.11.2011
comment
Джеймс, мы не знаем количество изображений, камера начинает отправлять поток, и когда мы получаем данные на нашем конце, мы получаем изображения из потока. - person Shafqat Ali; 17.11.2011
comment
камера начинает отправлять поток таким образом, и мы разделяем изображения в нашем приложении Content-Type: multipart / x-mixed-replace; border = - myboundary ... ...-- myboundary.Content-type: image / jpeg ... Двоичные данные JPEG № 1 (шестнадцатеричное представление = FFD8 .............. .................. FFD9) ...-- myboundary.Content-type: image / jpeg ... Двоичные данные JPEG № 2 (шестнадцатеричное представление = FFD8 .. .............................. FFD9):: ...-- myboundary.Content-type: image / jpeg .. . Двоичные данные JPEG № N (шестнадцатеричное представление = FFD8 ................................ FFD9) - person Shafqat Ali; 17.11.2011