当通过tcp c#接收图像时,随机获取参数异常和内存不足异常
本文关键字:异常 随机 获取 参数 内存不足 图像 tcp | 更新日期: 2023-09-27 18:14:27
我一直在绞尽脑汁想为什么会发生这种情况,它会运行几次很好,但它会随机接收长度为奇数(例如-123456,或者它会接收为0)。
然后当它要从流中生成图像时,它不能,因为长度错误。有时长度值看起来像一个正常的值,但当它去生成图像时,我仍然会得到参数异常。
编辑:我也随机接收"len"对象的大数,这会导致内存不足异常,但发送端从未发送任何与该数字一样大的东西,所以我不明白这个数字来自哪里。
接收代码:
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()");
}
}
}
发送代码:
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()");
}
}
}
假设Read/Receive
返回的恰好是您想要的数据量。事实并非如此。它最多返回那么多,并且至少返回一个字节。调整您的代码来处理这个事实。例如,通过使用BinaryReader
或在循环中读取,直到获得所需的字节数。
更好:停止使用套接字。使用一些更高级的东西,比如HTTP或web服务。套接字在大多数情况下是错误的解决方案。