154 lines
5.4 KiB
C#
154 lines
5.4 KiB
C#
using System.IO;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Windows.Media.Imaging;
|
|
|
|
namespace OperationControl.Models
|
|
{
|
|
public class TcpVideoReceiver
|
|
{
|
|
private readonly int _port;
|
|
private readonly System.Windows.Controls.Image _imageControl;
|
|
public readonly string imageName;
|
|
|
|
private volatile bool _rodando;
|
|
private Thread _thread;
|
|
private TcpListener _listener;
|
|
|
|
public TcpVideoReceiver(int port, System.Windows.Controls.Image imageControl)
|
|
{
|
|
_port = port;
|
|
_imageControl = imageControl;
|
|
imageName = imageControl.Name;
|
|
}
|
|
|
|
public void Iniciar()
|
|
{
|
|
if (_rodando) return;
|
|
|
|
_rodando = true;
|
|
_thread = new Thread(Run) { IsBackground = true };
|
|
_thread.Start();
|
|
}
|
|
|
|
public void Parar()
|
|
{
|
|
_rodando = false;
|
|
try
|
|
{
|
|
_listener?.Stop();
|
|
_imageControl.Source = null;
|
|
}
|
|
catch { /* ignora */ }
|
|
}
|
|
|
|
private void Run()
|
|
{
|
|
try
|
|
{
|
|
_listener = new TcpListener(IPAddress.Any, _port);
|
|
_listener.Start();
|
|
Console.WriteLine($"[VideoReceiver] Ouvindo na porta {_port}...");
|
|
|
|
while (_rodando)
|
|
{
|
|
TcpClient client = null;
|
|
|
|
try
|
|
{
|
|
// Em vez de bloquear direto no Accept, usamos Pending() + Sleep
|
|
if (!_listener.Pending())
|
|
{
|
|
Thread.Sleep(100);
|
|
continue;
|
|
}
|
|
|
|
client = _listener.AcceptTcpClient();
|
|
client.NoDelay = true;
|
|
Console.WriteLine("[VideoReceiver] Cliente conectado.");
|
|
|
|
using (var stream = client.GetStream())
|
|
using (var br = new BinaryReader(stream))
|
|
{
|
|
while (_rodando && client.Connected)
|
|
{
|
|
// 1) lê tamanho (4 bytes big-endian)
|
|
byte[] sizeBytes = br.ReadBytes(4);
|
|
if (sizeBytes.Length < 4)
|
|
break;
|
|
|
|
int size =
|
|
(sizeBytes[0] << 24) |
|
|
(sizeBytes[1] << 16) |
|
|
(sizeBytes[2] << 8) |
|
|
(sizeBytes[3]);
|
|
|
|
// 2) lê JPEG
|
|
byte[] imgBytes = br.ReadBytes(size);
|
|
if (imgBytes.Length < size)
|
|
break;
|
|
|
|
_imageControl.Dispatcher.BeginInvoke(new Action(() =>
|
|
{
|
|
try
|
|
{
|
|
using (var ms = new MemoryStream(imgBytes))
|
|
{
|
|
var bmp = new BitmapImage();
|
|
bmp.BeginInit();
|
|
bmp.CacheOption = BitmapCacheOption.OnLoad;
|
|
bmp.StreamSource = ms;
|
|
bmp.EndInit();
|
|
bmp.Freeze();
|
|
_imageControl.Source = bmp;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// ignora frame corrompido ou problema de decode
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
|
|
Console.WriteLine("[VideoReceiver] Cliente desconectado.");
|
|
client.Close();
|
|
}
|
|
catch (SocketException ex)
|
|
{
|
|
// WSACancelBlockingCall ao parar o listener é normal
|
|
if (!_rodando)
|
|
break;
|
|
|
|
Console.WriteLine("[VideoReceiver] SocketException: " + ex.Message);
|
|
client?.Close();
|
|
Thread.Sleep(500);
|
|
}
|
|
catch (IOException)
|
|
{
|
|
// desconexão abrupta do cliente
|
|
client?.Close();
|
|
Thread.Sleep(200);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("[VideoReceiver] Erro geral: " + ex.Message);
|
|
client?.Close();
|
|
Thread.Sleep(500);
|
|
}
|
|
}
|
|
|
|
Console.WriteLine("[VideoReceiver] Loop encerrado.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("[VideoReceiver] Erro ao iniciar listener: " + ex.Message);
|
|
}
|
|
finally
|
|
{
|
|
try { _listener?.Stop(); } catch { }
|
|
}
|
|
}
|
|
}
|
|
}
|