Ошибка при асинхронном чтении из NetworkStream - PullRequest
2 голосов
/ 15 ноября 2011

У меня есть приложение для связи с 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); }
    }

1 Ответ

0 голосов
/ 16 ноября 2011

Во-первых, асинхронные методы в сетевых потоках известны тем, что они теряют данные или никогда не возвращают данные! В вашем случае это может быть блокировка вызова 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 из нового потока в основной форме или классе вызывающего. Надеюсь, это поможет.

...