I've been racking my brain over why this is happening, it'll run several times very well but it'll randomly receive the length as an odd number (-123456 for example, or it'll receive as 0).
Then when it goes to make an image out of the stream it can't because the length was wrong. Sometimes the length value will look like a normal value but I'll still get the argument exception when it goes to generate the image.
Edit: I'm also randomly receiving large numbers for the "len" object which causes an Out Of Memory Exception, yet the send side never sends anything as large as that number so I don't understand where that number is coming from.
This is the receiving code:
public void ReceiveSS()
{
bool firstTimeRun = true;
TcpListener ssTcpListener = new TcpListener(IPAddress.Any, 63000);
TcpClient tcpReceiver = new TcpClient();
ssTcpListener.Start();
tcpReceiver = new TcpClient();
if (!uPnPWorks)
{
try
{
Console.WriteLine(contactIP + " " + port);
tcpReceiver.Connect(contactIP.ToString(), port);
}
catch (Exception)
{
}
}
else
{
tcpReceiver = ssTcpListener.AcceptTcpClient();
}
while (!ssStop)
{
try
{
//Start listening for connection.
if (tcpReceiver.Connected)
{
if (firstTimeRun)
{
//TCP connected. Receive images from contact.
NetworkStream receivedNs = new NetworkStream(tcpReceiver.Client);
BinaryReader br = new BinaryReader(receivedNs);
byte[] lenOfImage = new byte[4];
br.Read(lenOfImage, 0, 4);
int len = (int)(lenOfImage[0] << 24) | (int)(lenOfImage[1] << 16) | (int)(lenOfImage[2] << 8) | lenOfImage[3];
Console.WriteLine(len);
byte[] receivedData = new byte[len];
br.Read(receivedData, 0, receivedData.Length);
MemoryStream ms = new MemoryStream(receivedData, 0, receivedData.Length);
ms.Seek(0, SeekOrigin.Begin);
receivedNs.Flush();
Bitmap image = new Bitmap(ms);
receivedImage = image;
//Put image into picturebox.
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(delegate() { pboScreenShare.Image = image; }));
}
else { pboScreenShare.Image = image; }
//br.Close();
firstTimeRun = false;
}
else if (!firstTimeRun)
{
//TCP connected. Receive images from contact.
NetworkStream receivedNs = new NetworkStream(tcpReceiver.Client);
BinaryReader br = new BinaryReader(receivedNs);
byte[] lenOfImage = new byte[4];
br.Read(lenOfImage, 0, 4);
int len = (int)(lenOfImage[0] << 24) | (int)(lenOfImage[1] << 16) | (int)(lenOfImage[2] << 8) | lenOfImage[3];
try
{
MemoryStream ms = new MemoryStream();
if (len > 0)
{
byte[] receivedData = new byte[len];
br.Read(receivedData, 0, receivedData.Length);
ms = new MemoryStream(receivedData, 0, receivedData.Length);
ms.Seek(0, SeekOrigin.Begin);
}
receivedNs.Flush();
receivedImage2 = new Bitmap(ms); //Where I get the random argument exception
receivedImage2.MakeTransparent(Color.Pink);
Bitmap overlayedImage = new Bitmap(receivedImage.Width, receivedImage.Height);
using (Graphics gr = Graphics.FromImage(overlayedImage))
{
gr.DrawImage(receivedImage, new Point(0, 0));
gr.DrawImage(receivedImage2, new Point(0, 0));
}
//Put image into picturebox.
this.Invoke(new MethodInvoker(delegate() { pboScreenShare.Image = overlayedImage; }));
receivedImage2.Dispose();
receivedImage = overlayedImage;
//br.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + " Getting image");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString() + " ReceiveSS()");
}
}
}
Send code:
private void SendSS()
{
int cursorX = 0;
int cursorY = 0;
TcpListener listener = new TcpListener(IPAddress.Any, 63001);
listener.Start();
tcpClient = new TcpClient();
if (uPnPWorks)
{
tcpClient = listener.AcceptTcpClient();
}
else
{
try
{
tcpClient.Connect(contactIP, 63000);
}
catch (Exception)
{
}
}
bool firstTimeRun = true;
while (!ssStop)
{
try
{
if (tcpClient.Connected)
{
//Connected. Capture screen image.
if (firstTimeRun)
{
MemoryStream ssmemStream = new MemoryStream();
screenShotBMP = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Bitmap cursorBMP = CaptureCursor(ref cursorX, ref cursorY);
Graphics graphics = Graphics.FromImage(screenShotBMP as Image);
graphics.CopyFromScreen(0, 0, 0, 0, screenShotBMP.Size);
if (cursorBMP != null)
{
using (Graphics g = Graphics.FromImage(screenShotBMP))
{
Rectangle r = new Rectangle(cursorX, cursorY, cursorBMP.Width, cursorBMP.Height);
g.DrawImage(cursorBMP, r);
}
}
Bitmap saveScreenShot = screenShotBMP;
saveScreenShot.Save(ssmemStream, ImageFormat.Png);
NetworkStream ns = tcpClient.GetStream();
//Convert image to data.
BinaryWriter bw = new BinaryWriter(ns);
byte[] bytesToSend = ssmemStream.ToArray();
byte[] imageLen = new byte[4];
int len = bytesToSend.Length;
imageLen[0] = (byte)((len & 0xff000000) >> 24);
imageLen[1] = (byte)((len & 0x00ff0000) >> 16);
imageLen[2] = (byte)((len & 0x0000ff00) >> 8);
imageLen[3] = (byte)(len & 0xff);
ns.Write(imageLen, 0, 4);
ns.Write(bytesToSend, 0, bytesToSend.Length);
Console.WriteLine(bytesToSend.Length);
ns.Flush();
//bw.Close();
firstTimeRun = false;
}
else if (!firstTimeRun)
{
MemoryStream ssmemStream = new MemoryStream();
screenShotBMP2 = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Bitmap cursorBMP = CaptureCursor(ref cursorX, ref cursorY);
Graphics graphics = Graphics.FromImage(screenShotBMP2 as Image);
graphics.CopyFromScreen(0, 0, 0, 0, screenShotBMP2.Size);
if (cursorBMP != null)
{
using (Graphics g = Graphics.FromImage(screenShotBMP2))
{
Rectangle r = new Rectangle(cursorX, cursorY, cursorBMP.Width, cursorBMP.Height);
g.DrawImage(cursorBMP, r);
}
}
diffImage = ImageTool.GetDifferenceImage(screenShotBMP, screenShotBMP2, Color.Pink);
diffImage.Save(ssmemStream, ImageFormat.Png);
try
{
NetworkStream ns = tcpClient.GetStream();
//Convert image to data.
BinaryWriter bw = new BinaryWriter(ns);
byte[] bytesToSend = ssmemStream.ToArray();
byte[] imageLen = new byte[4];
int len = bytesToSend.Length;
Console.WriteLine(len);
imageLen[0] = (byte)((len & 0xff000000) >> 24);
imageLen[1] = (byte)((len & 0x00ff0000) >> 16);
imageLen[2] = (byte)((len & 0x0000ff00) >> 8);
imageLen[3] = (byte)(len & 0xff);
ns.Write(imageLen, 0, 4);
ns.Write(bytesToSend, 0, bytesToSend.Length);
Console.WriteLine(bytesToSend.Length);
ns.Flush();
//bw.Close();
}
catch
{
Console.WriteLine("iox exception");
}
screenShotBMP = screenShotBMP2;
}
}
}
catch (SocketException sockEx)
{
Console.WriteLine(sockEx.Message + " SendSS()");
}
}
}
You are assuming that Read/Receive
returns you exactly the amount of data you wanted. That is not the case. It returns you at most that much and at least one byte. Adapt your code to deal with that fact. For example, by using BinaryReader
or reading in a loop until you have got the required number of bytes.
Better yet: Stop using sockets. Use something higher-level like HTTP or web-services. Sockets are the wrong solution most of the time.