async / await TCP слушатель, сохраняющий изображения с камер - PullRequest
0 голосов
/ 11 апреля 2019

Привет, ребята. У меня большая проблема: я создал Windows-форму, которая работала в качестве сервера, прослушивающего TCP-сообщения, отправленные некоторыми камерами, подключенными к той же частной сети. Каждая камера отправляет tcp-сообщение на сервер, когда камера что-то обнаруживает, сервер должен работать непрерывно, не останавливая интерфейс графического интерфейса, и должен обрабатывать каждое TCP-сообщение. Обработка этих данных включает в себя сохранение изображения, снятого камерой отправителя. Сервер сохраняет эти изображения в папку, и здесь возникает моя проблема: сервер не может сохранить корректность каждого изображения: похоже, что некоторые байты были потеряны во время передачи, но я думаю, что все байты обогатили сервер, что-то более глубокое произошло. Может быть, я запрограммировал сервер async / await?

У меня есть список TcpListener, потому что мне нужно использовать больше серверов, по одному для каждой вкладки.

Вот как выглядят сохраненные изображения https://imgur.com/xtlgHPk https://imgur.com/CcvWbDH

Как видите, не полностью сохранен, кроме кого-то по неизвестной причине https://imgur.com/G25UPSS

    public void TcpServer(int port)
    {
        IPAddress ipAddress = null;
        string hostName = Dns.GetHostName();
        IPHostEntry ipHostInfo = Dns.GetHostEntry(hostName);
        for (int i = 0; i < ipHostInfo.AddressList.Length; ++i)
        {
            if (ipHostInfo.AddressList[i].AddressFamily ==
              AddressFamily.InterNetwork)
            {
                ipAddress = ipHostInfo.AddressList[i];
                _listener.Add( new TcpListener(ipAddress, port));
                ReceiveDataAsync();
                break;
            }
        }
        if (ipAddress == null)
            throw new Exception("No IPv4 address for server");

    }

    private async void ReceiveDataAsync()
    {
        try
        {
            _listener[tbServer.SelectedIndex].Start();
            while (true)
            {
                var tcpClient = await _listener[tbServer.SelectedIndex].AcceptTcpClientAsync();
                ReadDataFromClientAsync(tcpClient);
            }
        }
        catch (Exception e)
        {
            MessageBox.Show("Errore: ", e.Message.ToString());
        }
    }

    private async Task ReadDataFromClientAsync(TcpClient client)
    {
        try
        {
            using (NetworkStream stream=client.GetStream())
            {
                int selectedTabIndex, indexOfPort;
                string endPoint;
                while (client.Connected)
                {
                    int count = 0;
                    var countBytes = new byte[4];
                    for (int i = 0; i < 6; i++)
                    {
                        count = await stream.ReadAsync(countBytes, 0, countBytes.Length);
                    }
                    //The data dimension of the TCP message is into his header, 24th byte.
                    if (count == 0)
                    {
                        break;
                    }

                    byte[] bytes = new byte[BitConverter.ToUInt32(countBytes, 0)];
                    await stream.ReadAsync(bytes, 0, bytes.Length);


                    indexOfPort = Settings.getIndexOfPort(client.Client.LocalEndPoint.ToString());
                    endPoint = client.Client.RemoteEndPoint.ToString();
                    selectedTabIndex = Settings.getIndexOfPort(client.Client.LocalEndPoint.ToString());
                    updateGui("entry", indexOfPort,endPoint);

                    BufferData bufferService = new BufferData();
                    CameraMessage cameraMessage = await bufferService.writeBufferData(bytes.ToList());
                    if (cameraMessage == null)
                        return;

                  //doing some stuff

                        msgToShow = await bufferService.SaveImageFromCamera(cameraMessage);
                      //doing other stuff  

                    }
                    client.Close();
                    closeCommunication(selectedTabIndex,indexOfPort,endPoint);
                }
            }
        }
        catch (IOException e)
        {
            updateGui("stop");
        }

    }

Класс BufferData:

             public class BufferData
            {
              public async Task<CameraMessage> writeBufferData(List<byte> bytesList)
          {
        CameraMessage cameraMessage = new CameraMessage();

        try
        {
            int num = 0;
            int startSubData = 0;
            for (int startData = 0; startData < bytesList.Count-8; startData = startSubData + num)
            {

                int codeDataMessage = BitConverter.ToInt32(bytesList.GetRange(startData, 4).ToArray(), 0);
                int indexDataSize = startData + 4;
                int SizeDataMessage = BitConverter.ToInt32(bytesList.GetRange(indexDataSize, 4).ToArray(), 0);
                startSubData = indexDataSize + 4;
                byte[] array = bytesList.GetRange(startSubData, SizeDataMessage).ToArray();
                num = 0;
                switch (codeDataMessage)
                {
                    case 14020:
                        cameraMessage.image = await this.Base64ToImage(array);
                        num = this.OffSetStringType(SizeDataMessage);
                        break;
                }
            }
            return cameraMessage;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message.ToString());
            return null;
        }
    }

    public async Task<string> SaveImageFromCamera( CameraMessage cameraMessage)
    {
        string path = Settings.pathFolder + cameraMessage.ld_I_SN + @"\Images\";
        string res;
        if (!Directory.Exists(Settings.pathFolder+cameraMessage.ld_I_SN))
        {
            Directory.CreateDirectory(Settings.pathFolder + cameraMessage.ld_I_SN + @"\Images");
        }
            try
            {
            await Task.Run(() => { cameraMessage.image.Save(path + cameraMessage.ld_I_FILENAME, ImageFormat.Jpeg); });
                res = "#3 - OK - IMMAGINE SALVATA CON SUCCESSO";
                 cameraMessage.image.Dispose();
            return res;

        }
        catch (Exception ex)
            {
                res = "#3 - ERR - IMMAGINE NON SALVATA";
            return res;

        }


    }


    public async static Task<Image> Base64ToImage(byte[] imageBytes)
    {
        MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
        ms.Write(imageBytes, 0, imageBytes.Length);
        return System.Drawing.Image.FromStream(ms, true);
    }


}

1 Ответ

0 голосов
/ 14 апреля 2019

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

Когда вы вызываете await stream.ReadAsync(bytes, 0, bytes.Length), поток будет читать любое количество байтов от 1 до bytes.Length.Он вернет количество прочитанных байтов на самом деле .Вы должны принять это во внимание и прочитать снова, пока ваш буфер не был прочитан полностью.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...