TCP-клиент / сервер передачи изображений - PullRequest
2 голосов
/ 07 мая 2010

Я пытаюсь отправить изображение с помощью сокета TCP. Клиент без проблем подключается к серверу и начинает получать данные. Проблема в том, что когда я пытаюсь преобразовать поток в изображение с помощью метода FromStream (), я получаю исключение OutOfMemory. Может кто-нибудь мне помочь? Действительно важно !! Вот код:

фрагмент клиента



private void btnConnect_Click(object sender, EventArgs e)
        {
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
            TcpClient client = new TcpClient();</p>

<pre><code>        client.Connect(ipAddress, 9500);
        NetworkStream nNetStream = client.GetStream();

        while (client.Connected)
        {
            lblStatus.Text = "Connected...";
            byte[] bytes = new byte[client.ReceiveBufferSize];
            int i;
            if (nNetStream.CanRead)
            {
                nNetStream.Read(bytes, 0, bytes.Length);  

                Image returnImage = Image.FromStream(nNetStream); //exception occurs here
                pictureBox1.Image = returnImage;
            }
            else
            {
                client.Close();
                nNetStream.Close();
            }


        }
        client.Close();
    }

Фрагмент сервера


try
            {
                IPAddress ipAddress = Dns.Resolve("localhost").AddressList[0];
                TcpListener server = new TcpListener(ipAddress, 9500);
                server.Start();
                Console.WriteLine("Waiting for client to connect...");

                while (true)
                {
                    if (server.Pending())
                    {
                        Bitmap tImage = new Bitmap(Image URL goes here);
                        byte[] bStream = ImageToByte(tImage);

                        while (true)
                        {
                            TcpClient client = server.AcceptTcpClient();
                            Console.WriteLine("Connected");
                            while (client.Connected)
                            {
                                NetworkStream nStream = client.GetStream();
                                nStream.Write(bStream, 0, bStream.Length);
                            }
                        }
                    }
                }

            }


            catch (SocketException e1)
            {
                Console.WriteLine("SocketException: " + e1);
            }
        }
        static byte[] ImageToByte(System.Drawing.Image iImage)
        {
            MemoryStream mMemoryStream = new MemoryStream();
            iImage.Save(mMemoryStream, System.Drawing.Imaging.ImageFormat.Gif);
            return mMemoryStream.ToArray();
        }

Большое спасибо за продвинутый,

Ответы [ 5 ]

4 голосов
/ 05 сентября 2011

Есть пара неправильных вещей, в том числе, возможно, протокол, который вы используете. Сначала клиент:

  • Если вы ожидаете одно изображение, петля while
  • Ваш клиент сначала выполняет Read, который считывает некоторую информацию с сервера в буфер, а затем вызывает Image.FromStream(nNetStream), который считывает неполные данные.
  • Всякий раз, когда вы читаете из потока, имейте в виду, что один вызов Read не гарантирует заполнение вашего буфера. Он может вернуть любое количество байтов от 0 до размера вашего буфера. Если он возвращает 0, это означает, что больше нечего читать. В вашем случае это также означает, что ваш клиент в настоящее время не может узнать, сколько нужно читать с сервера. Решение здесь состоит в том, чтобы сервер отправлял длину изображения в качестве первой части информации. Другое решение состоит в том, чтобы сервер отключил клиента после того, как он отправил информацию. Это может быть приемлемо в вашем случае, но не будет работать, если вам нужны постоянные соединения (например, пул соединений на стороне клиента).

Клиент должен выглядеть примерно так (при условии, что сервер отключит его после отправки данных):

IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
using (TcpClient client = new TcpClient())
{
    client.Connect(ipAddress, 9500);
    lblStatus.Text = "Connected...";

    NetworkStream nNetStream = client.GetStream();
    Image returnImage = Image.FromStream(nNetStream);
    pictureBox1.Image = returnImage;
}

Далее сервер:

  • Вместо Pending вы можете просто принять клиента
  • Сервер отправляет поток снова и снова одному и тому же клиенту, пока они не отключатся. Вместо этого отправьте его только один раз.

Цикл сервера должен выглядеть примерно так:

Bitmap tImage = new Bitmap(Image URL goes here);
byte[] bStream = ImageToByte(tImage);

while (true)
{
    // The 'using' here will call Dispose on the client after data is sent.
    // This will disconnect the client
    using (TcpClient client = server.AcceptTcpClient())
    {
        Console.WriteLine("Connected");
        NetworkStream nStream = client.GetStream();

        try
        {
            nStream.Write(bStream, 0, bStream.Length);
        }
        catch (SocketException e1)
        {
            Console.WriteLine("SocketException: " + e1);
        }
    }
}
1 голос
/ 17 июня 2013

Я рекомендую вам использовать этот код (я создал его сам, проверил и он отлично работает):

public void Bitmap ConvertByteArrayToBitmap(byte[] receivedBytes)
{
   MemoryStream ms = new MemoryStream(receivedBytes);
   return new Bitmap(ms, System.Drawing.Imaging.ImageFormat.Png); // I recomend you to use png format   
}

Используйте это, чтобы преобразовать полученный byteArray в изображение.

1 голос
/ 07 мая 2010

Эта часть мне кажется прикольной:

  byte[] bytes = new byte[client.ReceiveBufferSize]; 
  int i; 
  if (nNetStream.CanRead) 
  { 
    nNetStream.Read(bytes, 0, bytes.Length);   

    Image returnImage = Image.FromStream(nNetStream); //exception occurs here 

Сначала вы читаете client.ReceiveBufferSize байтов в массив "байтов", а затем вы приступаете к построению изображения из того, что осталось в потоке. А как насчет байтов, которые вы только что прочитали в "байтах"?

0 голосов
/ 23 марта 2012

Вот решение:

Серверная сторона:

tImage.Save(new NetworkStream(client), System.Drawing.Imaging.ImageFormat.Png);

Сторона клиента:

byte[] b = new byte[data.ReceiveBufferSize];
client.Receive(b);
MemoryStream ms = new MemoryStream(b);
Image receivedImag = Image.FromStream(ms);

или:

Image receivedImag = Image.FromStream(new NetworkStream(client));
0 голосов
/ 07 мая 2010

Похоже, ваш сервер отправляет изображение снова и снова:

while (client.Connected)
{
    NetworkStream nStream = client.GetStream();
    nStream.Write(bStream, 0, bStream.Length);
}

Если сервер может отправлять данные достаточно быстро, клиент, вероятно, будет продолжать получать их.

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