我正在制作一个发送和接收小图片的网络摄像头应用。我已经使它能够发送和接收,我在127.0.0.1上测试它工作正常,但现在我使用自己的外部IP地址,它似乎发送一个图像,接收一个,然后搞砸了,我得到图像大小中的某种大整数值,一个负值导致它崩溃,我想也许接收和发送是自己运行的,并且以某种方式不同步。我在发送每张图片之前放了1000毫秒的延迟,虽然它很慢但工作正常,但是当我把延迟拿出来时,它就会混乱。
以下是代码:
// This sends.
private void NewFrameReceived(object sender, NewFrameEventArgs e)
{
Bitmap img = (Bitmap)e.Frame.Clone();
byte[] imgBytes = EncodeToJpeg(img, 25).ToArray();
if (_tcpOut.Connected)
{
NetworkStream ns = _tcpOut.GetStream();
if (ns.CanWrite)
{
System.Threading.Thread.Sleep(500);
ns.Write(BitConverter.GetBytes(imgBytes.Length), 0, 4);
ns.Write(imgBytes, 0, imgBytes.Length);
}
}
}
// This receives.
private void listeningThread_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
// start listening for connections
_tcpIn = new TcpListener(IPAddress.Any, 54321);
_tcpIn.Start();
TcpClient _inClient = _tcpIn.AcceptTcpClient();
while (true)
{
NetworkStream ns = _inClient.GetStream();
if (ns.CanRead && ns.DataAvailable)
{
Byte[] imgSizeBytes = new Byte[4];
ns.Read(imgSizeBytes, 0, 4);
int imgSize = BitConverter.ToInt32(imgSizeBytes, 0);
Byte[] imgBytes = new Byte[imgSize]; <-- ERROR, GET CRAZY LARGE VALUE
ns.Read(imgBytes, 0, imgSize);
MemoryStream ms = new MemoryStream(imgBytes);
Image img = Image.FromStream(ms);
picVideo.Image = img;
}
}
}
答案 0 :(得分:3)
你需要重新思考一下......数据可以到达不同的数据包。您的读取功能仅读取可用内容。这将导致您的系统失去同步。
我为图像构建了一个小协议,所以我总能分辨出图像的开始和结束在我的数据流中。
你不必这样做,但它会让生活变得更轻松,你可以纯粹通过一个简单的状态机来完成它,它知道它接收到的图像有多远。但是,发送图像时的任何不合规(例如流中的1个额外字节)都可能使事物永远不同步。
答案 1 :(得分:1)
Read
不一定读取你要求的字节数,就像许多当前可用的字节一样 - 你应该检查返回值以查看它读取的数量。 documentation可能有助于您更好地理解。
您应该添加逻辑以保持读取,直到读取了所有图像字节。一个伪代码示例:
total_bytes_read = 0;
while (total_bytes_read != total_bytes_needed)
{
bytes_left_to_read = total_bytes_needed - total_bytes_read;
total_bytes_read += read(buffer, total_bytes_read, bytes_left_to_read);
}