1

好的,所以我见过很多人遇到这个问题,我在某种程度上发现了可能导致问题的原因,但我不知道如何解决它。基本上,我正在尝试通过套接字将屏幕截图从客户端发送到服务器。我在客户端应用程序上截取屏幕截图并使用此方法将其转换为字节数组:

// Convert bitmap to byte method
public static byte[] ImageToByte(Bitmap bitmap)
{
    byte[] imageData;
    using (var stream = new MemoryStream())
    {
        bitmap.Save(stream, ImageFormat.Png);
        imageData = stream.ToArray();
        return imageData;
    }
}

然后我将字节数组的长度和字节数组发送到服务器。服务器在收到长度后,使用此方法获取实际数据(这是该方法的一部分,因为它大部分不相关):

void dataRecieveCallback(IAsyncResult ar)
{
    try
    {
        int rec = sck.EndReceive(ar);

        if (rec <= 0)
        {
            return;
        }

        recieveBuffer.bufStream.Write(recieveBuffer.buffer, 0, rec);
        recieveBuffer.toRecieve -= rec;

        if (recieveBuffer.toRecieve > 0)
        {
            Array.Clear(recieveBuffer.buffer, 0, recieveBuffer.buffer.Length);
            recieveBuffer.bufStream.Position = 0;
            sck.BeginReceive(recieveBuffer.buffer, 0, recieveBuffer.buffer.Length, SocketFlags.None, dataRecieveCallback, null);
            return;
        }

        // Convert all recieved data in memory stream to a byte array
        byte[] finalBuffer = recieveBuffer.bufStream.ToArray();

然后我使用finalBuffer来尝试获取图像,但每当我这样做时,使用此方法:

        TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
        Bitmap screenShot = (Bitmap)tc.ConvertFrom(finalBuffer);

我总是得到一个System.ArgumentException来自System.Drawing.ImageFromStream:“参数无效”。这段代码可以很好地发送字符串,但是每当我尝试发送图像时它就不起作用。我很确定这是套接字代码的问题,因为我尝试通过截屏在本地执行此操作,使用相同的方法将其转换为字节数组,然后使用相同的方法将其转换回来,并且它有效。有人知道我的代码有什么问题吗?

这是缓冲区的部分代码

struct RecBuffer 
{ 
   public const int BUFFER_SIZE = 1024;
   public byte[] buffer;
   public int toRecieve;
   public MemoryStream bufStream;

   public RecBuffer(int toRec) 
   {
      buffer = new byte[BUFFER_SIZE];
      toRecieve = toRec;
      bufStream = new MemoryStream(toRecieve);
   }
}

我使用了本教程中的大量代码。至少对于接收部分。

4

1 回答 1

1

我认为问题出在您的dataRecieveCallback功能上。在那里,您将 bufStream 的位置重置为零:

if (recieveBuffer.toRecieve > 0)
{
  Array.Clear(recieveBuffer.buffer, 0, recieveBuffer.buffer.Length);
  recieveBuffer.bufStream.Position = 0; // <--Here
  sck.BeginReceive(recieveBuffer.buffer, 0, recieveBuffer.buffer.Length, SocketFlags.None, dataRecieveCallback, null);
  return;
}

这意味着您将在系统下次调用您的回调函数时覆盖已经收到的字节。

所以,只需删除该行

recieveBuffer.bufStream.Position = 0;

并且您的代码应该可以正常工作。

于 2012-11-10T08:57:22.670 回答