在我的項目中,我需要通過UDP接收視頻。源IP地址爲224.0.0.21,宿端IP爲169.254.170.141。我通過端口3956接收視頻(這是來自Wireshark的有效信息)。我使用SharpPcap接收UDP流量,但它沒有加入組播的方法。我嘗試從MSDN這個代碼,但它不工作。不能加入組播組c#
IPAddress multicastaddress = IPAddress.Parse("224.0.0.21");
IPEndPoint remoteep = new IPEndPoint(IPAddress.Any, 3956);
m_ClientTarget.JoinMulticastGroup(multicastaddress, localAddr);
在我的電腦中,我有一些網絡適配器,但我使用設備的IP地址,連接到源視頻。源和宿直接連接。當我在wireshark中啓動監視器流量時,我的程序也會收到數據包,但是如果沒有wireshack,它就不能執行它。 我的代碼:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SharpPcap;
using SharpPcap.LibPcap;
using SharpPcap.AirPcap;
using SharpPcap.WinPcap;
using System.IO;
using System.Net.Sockets;
using System.Net;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Threading;
namespace GVSPCapture
{
public partial class Form1 : Form
{
static int frameCounter = 0;
static byte[] pixels = new byte[1920 * 1080 * 3];
static IPAddress fpgaAddr = IPAddress.Parse("224.0.0.21");
static IPAddress localAddr = IPAddress.Parse("169.254.170.141");
static MulticastOption mcastOption = new MulticastOption(fpgaAddr, localAddr);
private static UdpClient m_ClientTarget = new UdpClient(3956);
private static IPAddress m_GrpAddr;
const int GroupPort = 3956;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
findDevices();
}
public void findDevices()
{
string ver = SharpPcap.Version.VersionString;
var devices = CaptureDeviceList.Instance;
foreach (var dev in devices)
{
lbxDevices.Items.Add(dev.Name + dev.Description);
}
}
private void JoinVideoMulticast()
{
IPAddress multicastaddress = IPAddress.Parse("224.0.0.21");
IPEndPoint remoteep = new IPEndPoint(IPAddress.Any, 3956);
m_ClientTarget.JoinMulticastGroup(multicastaddress, IPAddress.Parse("169.254.170.141"));
while (true)
{ }
}
private void startCapture(ICaptureDevice dev)
{
if (!dev.Started)
{
dev.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival);
int readTimeoutMilliseconds = 1000;
if (dev is AirPcapDevice)
{
// NOTE: AirPcap devices cannot disable local capture
var airPcap = dev as AirPcapDevice;
airPcap.Open(SharpPcap.WinPcap.OpenFlags.DataTransferUdp, readTimeoutMilliseconds);
}
else if (dev is WinPcapDevice)
{
var winPcap = dev as WinPcapDevice;
winPcap.Open(SharpPcap.WinPcap.OpenFlags.DataTransferUdp | SharpPcap.WinPcap.OpenFlags.NoCaptureLocal, readTimeoutMilliseconds);
}
else if (dev is LibPcapLiveDevice)
{
var livePcapDevice = dev as LibPcapLiveDevice;
livePcapDevice.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
}
else
{
throw new System.InvalidOperationException("unknown device type of " + dev.GetType().ToString());
}
dev.StartCapture();
Thread recvThread = new Thread(JoinVideoMulticast);
recvThread.Start();
}
}
delegate void SetTextCallback(string text);
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.tbxCnt.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.tbxCnt.Text = text;
}
}
private void device_OnPacketArrival(object sender, CaptureEventArgs e)
{
var time = e.Packet.Timeval.Date;
var len = e.Packet.Data.Length;
if (len == 572)
{
var tmp = e.Packet.Data;
int packet_id = tmp[47] << 16 | tmp[48] << 8 | tmp[49];
int startPos = (packet_id - 1) * 522;
for (int i = 50; i < tmp.Length; i+=3)
{
pixels[startPos + i + 0 - 50] = tmp[i];
pixels[startPos + i + 1 - 50] = tmp[i];
pixels[startPos + i + 2 - 50] = tmp[i];
}
}
if (len == 60)
{
var im = CopyDataToBitmap(pixels);
pictbFrame.Image = im;
frameCounter += 1;
SetText(frameCounter.ToString());
}
}
public Bitmap CopyDataToBitmap(byte[] data)
{
GCHandle pinned = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr ptr = pinned.AddrOfPinnedObject();
BitmapData dt = new BitmapData();
dt.Scan0 = ptr;
dt.Stride = 5760;
dt.Width = 1920;
dt.Height = 1080;
dt.PixelFormat = PixelFormat.Format24bppRgb;
Bitmap btm = new Bitmap(1920, 1080, 5760, PixelFormat.Format24bppRgb, dt.Scan0);
return btm;
}
private void btnStart_Click(object sender, EventArgs e)
{
int devNum = lbxDevices.SelectedIndex;
if (devNum > 0)
{
var device = CaptureDeviceList.Instance[devNum];
startCapture(device);
}
}
private void btnStop_Click(object sender, EventArgs e)
{
int devNum = lbxDevices.SelectedIndex;
if (devNum > 0)
{
var device = CaptureDeviceList.Instance[devNum];
if (device.Started)
{
device.StopCapture();
device.Close();
}
}
m_ClientTarget.DropMulticastGroup(fpgaAddr);
}
}
}
一個問題是,是,是保留給路由器功能的多播地址,你不應該試圖加入它擺在首位的PC上。 –
@RonMaupin加入多播地址有什麼不好? –
當多播組被保留用於不同的目的時,這是不好的。該多播組不應該用於視頻。有一個多播地址塊('239.0.0.0-239.255.255.255'組織本地範圍)爲這種類型保留。這就像試圖將屬於Google的IP地址用於您自己的目的。 IANA維護_ [IPv4多播地址空間註冊表](https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml)_,其方式與維護單播地址分配的方式相同。 –