karan ugale

karan ugale

  • 1.6k
  • 84
  • 1.6k

"Parameter is not valid" TCP Screen Sharing Program [C#]

Nov 4 2022 2:57 PM

I know this is a common question people ask but for days I have been researching and couldn't find a way that will help me.

I'm developing a screen sharing program and using TCP to send the desktop screenshots over the networkstream. I tried using UDP but later discovered that it has a message size limit of 65,507 bytes and I have way more bytes in a single message so I use TCP.

When I run the program I get some of the images and if the bytes size is increased then it while converting the bytes to image it throws

Exception thrown: 'System.ArgumentException' in System.Drawing.dll
System.ArgumentException: Parameter is not valid.

As far as I have read everywhere is networkstream takes time to read all the bytes sent from the server and if the server send another data before the networkstream finish the reading then the byte array will have insufficient data in it and hence it will throw the error. I also tried Thread.Sleep(milliseconds) but again I cannot predict the time to wait and it will make process much slower.

Is there any way I can wait for networkstream write to let networkstream read all the bytes that are sent and continue sending and waiting but this has to be fast as there are sets of images that combining makes a video in picturebox of client.

Code:

Server

private void receiveScreenShare()
{
    TcpListener list = new TcpListener(IPAddress.Parse("192.168.0.102"), 4567);
    list.Start();
    TcpClient client = list.AcceptTcpClient();
    NetworkStream streamScreenShare = client.GetStream();
    while (true)
    {
        try
        {
            byte[] bytes = new byte[1000000];
            streamScreenShare.Read(bytes, 0, bytes.Length);
            ImageConverter convertData = new ImageConverter();
            Image image = (Image)convertData.ConvertFrom(bytes); //Here is the error
            pictureBox1.Image = image;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
}

Client

byte[] b1 = null;
private void sendScreen()
{
    try
    {
        TcpClient client = new TcpClient("192.168.0.102", 4567);
        while (true)
        {
            NetworkStream streamScreen = client.GetStream();
            //Get Screenshot
            Bitmap bm = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            Graphics g = Graphics.FromImage(bm);
            g.CopyFromScreen(0, 0, 0, 0, bm.Size);
            //Convert Screenshot to byte
            Bitmap newBM = new Bitmap(bm, new Size(bm.Width / 2, bm.Height / 2));
            MemoryStream ms = new MemoryStream();
            bm.Save(ms, ImageFormat.Jpeg);
            //Write Screenshot into stream
            b1 = ms.ToArray();
            streamScreen.Write(b1, 0, b1.Length);
        
            Thread.Sleep(500);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

I have referred these questions too:

  1. c# tcp How can i get exacly amount of bytes that are recived?
  2. C# TCP Read All Data - Server Side Issues

Working with the methods stated in above solutions I have found that the networkstream tries to read the bytes but the client still sends data to the server and server goes into infinite loop because it's receiving data every millisecond.


Answers (2)