-1

i have made a simple program that takes a screenshot, encrypt it to base64 and send it over Socket connection, it works fine on my laptop (Windows 7), but when i tried it on other computer (Windows XP), it says "Parameter is not valid" when i'm trying to convert back the base64 text to an image, here is my code :

Client :

public static Image Do_CaptureDesktop()
{
    Rectangle bounds = default(Rectangle);
    System.Drawing.Bitmap screenshot = null;
    Graphics graph = default(Graphics);
    bounds = Screen.PrimaryScreen.Bounds;
    screenshot = new Bitmap(
                     bounds.Width, 
                     bounds.Height, 
                     System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    graph = Graphics.FromImage(screenshot);
    graph.CopyFromScreen(
                     bounds.X, 
                     bounds.Y, 0, 0, 
                     bounds.Size,      
                     CopyPixelOperation.SourceCopy);
    return screenshot;
}
public static string Do_ImageToBase64(Image image,
              System.Drawing.Imaging.ImageFormat format)
{
    using (MemoryStream ms = new MemoryStream())
    {
        // Convert Image to byte[]
        image.Save(ms, format);
        byte[] imageBytes = ms.ToArray();

        // Convert byte[] to Base64 String
        string base64String = Convert.ToBase64String(imageBytes);
        return base64String;
    }
}
public static void Do_prepareImage()
{
    Image screen = Do_CaptureDesktop();
    string base64Screen = Do_ImageToBase64(screen, ImageFormat.Png);
    byte[] Screens = Encoding.Unicode.GetBytes(base64Screen);
    byte[] Header = Encoding.Unicode.GetBytes("S1");
    byte[] Datas = new byte[Screens.Length + Header.Length];
    Header.CopyTo(Datas, 0);
    Screens.CopyTo(Datas, Header.Length);
    Socket.Send(Datas);
}
private static void ConnectToServer()
{
    int attempts = 0;

    while (!_clientSocket.Connected)
    {
        try
        {
            attempts++;
            Console.WriteLine("Connection attempt " + attempts);
            try
            {
                _clientSocket.Connect(IPAddress.Parse("192.168.1.1"), 100);
            }
            catch (SocketException)
            {

             }
        }
        catch (SocketException)
        {
            Console.Clear();
        }
    }
    Console.Clear();
    Console.WriteLine("Connected");

}
static void Main(string[] args)
{
    ConnectToServer();
    Do_prepareImage();
}

Server :

public static Image Base64ToImage(string base64String)
{
    // Convert Base64 String to byte[]
    byte[] imageBytes = new byte[4];
    try
    {
        imageBytes = Convert.FromBase64String(base64String);
    }
    catch (Exception)
    {
    }
    MemoryStream ms = new MemoryStream(imageBytes, 0,
                                 imageBytes.Length);

    // Convert byte[] to Image
    ms.Write(imageBytes, 0, imageBytes.Length);
    Image image = Image.FromStream(ms, true); //Here is the error
    return image;
}

public static void ParsePacket(string packet)
{
    if (packet.Substring(1,1).Equals("1"))
    {
        string stringImage = packet.Substring(2, packet.Length - 2); 
        //The line above remove the packet name and leave just the base64 text
        try
        {
            Image screen = Base64ToImage(stringImage);
            pictureBox1.Image = screen;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }


    }

}

I have another function in the server side that send the received packet to "ParsePacket" function. Edit : I Repeat that it works fine on Windows 7.

iabbott
  • 873
  • 1
  • 8
  • 23
user2695010
  • 21
  • 1
  • 4
  • What line is the error happening at? – iabbott Sep 12 '13 at 15:45
  • base64 is not encryption. You _encode_ / decode to/from Base64. – Mat Sep 12 '13 at 15:46
  • Okay Mat thank you for your correction :) @iabbott : Image image = Image.FromStream(ms, true); //Here is the error – user2695010 Sep 12 '13 at 15:47
  • you should remove the line `ms.Write(imageBytes, 0, imageBytes.Length);`! the stream already contains the bytes after construction... maybe the messed up stream position causes the exception – olydis Sep 12 '13 at 15:49
  • @olydis I removed it but it sill working on Win 7 not on Win XP, thanks for your answer any way. – user2695010 Sep 12 '13 at 15:53
  • 1
    what might be helpful is if you gave us the base64 encoded string you get that will not decode. – John Faulkner Sep 12 '13 at 15:55
  • hmmm weird, this should absolutely work then (did EXACTLY the same under XP once), either invalid data comes from networking or maybe you are using an image encoder under Win 7 that Win XP does not have a decoder for? rather unlikely I guess... – olydis Sep 12 '13 at 15:56
  • Olydis, i'm not using any decoder, the same exacts client application works on Windows 7 but not on Windows Xp, you think it may be a problem from the computer ? – user2695010 Sep 12 '13 at 16:04
  • @user2695010 Can you save the b64 string out and post it? it could be an issue with the string length - different screen resolutions - although I see you are using a 4byte boundary - it would be easy to get a look at the decoding and see what it decodes to if we had the string. – John Faulkner Sep 12 '13 at 16:09
  • That's strange ! http://cyclops-serveur.com/Win7.txt http://cyclops-serveur.com/WinXP.txt The first one's size is 136KB, but the second's only 36.7KB :o – user2695010 Sep 12 '13 at 16:17
  • yes, its also an invalid length. you can pad it with a single = at the end to see what it decodes to. – John Faulkner Sep 12 '13 at 16:26
  • I didn't understand "to see what it decodes to", it decodes to an image, no ? – user2695010 Sep 12 '13 at 16:28
  • I think the problem lies in the code you have not posted. You say its client to server, my suspicion is that you are not correctly reading the entire "packet" from the network stream. – Ashigore Sep 12 '13 at 16:32
  • @Ashigore : But When i try on a Windows 7 it works fine – user2695010 Sep 12 '13 at 16:36
  • it decodes to an invalid string length for base64 - if you add an = to the end for padding then it will decode to a binary file. yes, probably an image. I didn't look. – John Faulkner Sep 12 '13 at 16:36
  • Please post the server code where you read the data from the network connection. – Iridium Sep 12 '13 at 17:37
  • You may also want to have a look at my answer here: http://stackoverflow.com/questions/5527670/socket-is-not-working-as-it-should-help/5575287#5575287 which demonstrates a fully-functional example of a client sending screenshots to a server application using sockets. – Iridium Sep 12 '13 at 19:12

2 Answers2

2

I think the problem is you are ignoring errors generated by:

try
{
    imageBytes = Convert.FromBase64String(base64String);
}
catch (Exception)
{
}

Therefore when you call:

Image image = Image.FromStream(ms, true);

You are parsing an empty array of 4 bytes (why did you even initialise it to this?) Hense the error.

The method is generally terribly written, change it to this and see what the error really is:

public static Image Base64ToImage(string base64String)
{
    byte[] imageBytes = Convert.FromBase64String(base64String);
    using (MemoryStream ms = new MemoryStream(imageBytes))
    {
        return Image.FromStream(ms, true);
    }
}
Ashigore
  • 4,618
  • 1
  • 19
  • 39
0

Although your receive method in the server is not included I think you run into a problem I've seen several times here on SO: Receiving data via TCP can give you just a part of the sent message as well as multiple messages together that were sent in almost the same time.

As I see in your client code, you don't have any length information or end token in your protocol between client and server. You need some kind of information to recognize if you have received the complete message or just a part of it (or even two messages received in one burst).

In the receive method of the server you have to store the received data in a buffer until you know (according to your protocol) that you have received a complete message. The you can process this message and remove it from the buffer.

I guess the error message is the result of a non-complete message that should be converted into an image.

The code works on the localhost because the message can be sent over the loopback device without spliting it and therefor you receive it in one part.

Roland Bär
  • 1,720
  • 3
  • 22
  • 33