【问题标题】:Parameter is not valid - error when sending a bitmap via TCP with C#参数无效 - 使用 C# 通过 TCP 发送位图时出错
【发布时间】:2012-04-04 17:59:47
【问题描述】:

我有一个文件传输程序。程序(客户端)执行以下操作以通过 TCP 套接字发送位图:获取屏幕截图 -> 从内存中抓取位图 -> 转换为流 -> 发送

        MemoryStream Fs = new MemoryStream();

//////////////11111
        Bitmap bmp = TakeScreen();

///////////////2222
        //Bitmap bmp = new Bitmap(@"C:\temp\001.bmp");


        bmp.Save(Fs, ImageFormat.Bmp);
        Byte[] buffer = Fs.ToArray();

        Fs.Read(buffer, 0, buffer.Length);
        TcpClient socket = new TcpClient("192.168.0.131", 1095);

        NetworkStream nw = socket.GetStream();
        nw.Write(buffer, 0, buffer.Length);
        nw.Close();
        Fs.Dispose();
        socket.Close();
        bmp.Dispose();
  • 如果我选择直接从内存中传输图像 - 没有错误。

  • 如果我首先尝试从文件加载位图 - 在服务器端出现“参数无效”错误。

这里是服务器端:

                    NetworkStream Nw = new NetworkStream(handlerSocket.Client);
                    int thisRead = 0;
                    int Blocksize = 1024;
                    Byte[] dataByte = new Byte[Blocksize];

                    Bitmap screen = getScreen(Nw, dataByte, thisRead, Blocksize);
                    Nw.Close();

和

   private Bitmap getScreen(NetworkStream Nw, Byte[] dataByte, int thisRead, int Blocksize)
    {
        Bitmap bitmap;
        using (var strm = new MemoryStream())
        {

            while (true)
            {
                thisRead = Nw.Read(dataByte, 0, Blocksize);
                strm.Write(dataByte, 0, thisRead);
                if (thisRead == 0)
                    break;
            }

            bitmap = new Bitmap(strm); // Error here
        }
        Bitmap bm3 = new Bitmap(bitmap);
        bitmap.Dispose();
        return bm3;
    }

是什么导致了这个错误?我猜它与 MemoryStream 有关。

编辑:简化问题

【问题讨论】:

  • 您应该真正更改 TCP 通信以包含您正在传输的二进制信息的大小。当前,服务器在尝试创建位图之前可能没有完整的位图信息。例如,在发送位图信息之前,将位图的大小发送为long。这样,服务器就知道需要多少字节。

标签: c# winforms bitmap file-transfer


【解决方案1】:

您需要先搜索到流的开头,然后才能在getScreen 中创建Bitmap。

private Bitmap getScreen(NetworkStream Nw, Byte[] dataByte, int thisRead, int Blocksize)
{
    Bitmap bitmap;
    using (var strm = new MemoryStream())
    {
        while (true)
        {
            thisRead = Nw.Read(dataByte, 0, Blocksize);
            strm.Write(dataByte, 0, thisRead);
            if (thisRead == 0)
               break;
        }

        stream.Seek(0, SeekOrigin.Begin; // <-- Go Back to beginning of stream
        bitmap = new Bitmap(strm); // Error here
    }
    Bitmap bm3 = new Bitmap(bitmap);
    bitmap.Dispose();
    return bm3;
}

编辑
详细解释: 将最后一个字节写入流后,流的当前位置是流的末尾。现在从屏幕创建Bitmap 会尝试从流中读取位图,但这不起作用,因为在当前位置(= 流的末尾)之后没有更多数据。

所以你需要做的是告诉流将当前位置设置回流的开头。然后就可以读取位图信息了。

【讨论】:

  • 我添加了“strm.Seek(0, SeekOrigin.Begin);”正如你所建议的那样,但在同一行发生了同样的错误。我不确定你解释的问题是否属实,因为我可以很好地从内存中发送图像,而无需使用 Seek()
  • 您编写的以字节形式获取位图的代码也很奇怪。您正在将位图写入内存流。然后你得到内存流的字节缓冲区(它已经包含位图的字节),之后你再次读取流,这是多余的。也许您现在是我在对该问题的评论中写的内容的受害者,即:您确定在服务器尝试创建位图之前将整个位图传输到服务器吗?您是否尝试过将接收到的内容存储到文件中并使用 Paint 打开它?`
  • niiice .. 你可能没有注意到,但你刚才的帖子一劳永逸地解决了我的问题。如你所说,我曾经“阅读”流 2 次一行,所以我注释掉了“//Fs.Read(buffer, 0, buffer.Length);”,令我惊讶的是——图像传输完美无瑕!我不知道为什么即使在流的“第二次读取”的情况下,直接从“内存”传输也能工作……顺便说一句,是的,我在 Paint、Xnview 等中打开了图像。尺寸、尺寸、颜色正是在客户端和服务器上相同。无论如何,问题解决了,谢谢你的建议@Thorsten Dittmar!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-16
  • 2016-02-20
  • 2012-12-20
  • 2013-07-21
相关资源
最近更新 更多