[英]Sending and receiving UDP packets between two programs on the same computer
[英]UDP Multicast between two sockets in the same process
我正在為處理UDP多播通信的類編寫一些測試。 我將測試設計為使用環回接口(127.0.0.1)進行測試,因為我不希望它們干擾網絡上的其他程序/設備。
在我的“單元測試”中,我有一個經過測試的套接字,該套接字連接了給定的多播組並綁定到127.0.0.1,而發送方套接字也加入了相同的多播組並綁定到127.0.0.1,兩者當然都是在同一過程中進行的。
為確保消息已發送,我有另一個測試程序(另一個過程),該程序也加入了多播組並輸出發送給它的所有內容。
問題是我的測試套接字從未收到發送方發送的內容,而測試程序(因此另一個進程)收到了它。
多個套接字/多播/本地主機的組合有一些限制嗎?
新的消息:
我的錯誤是認為本地主機上的UDP 可能是可靠的。 下面的測試程序顯示,偵聽套接字從未接收到第一個UDP數據包(至少在我的計算機上)(但其他進程仍接收到它)。
在我的單元測試中,我正在發送一個數據包並期望有特定的答案:我負擔不起兩次發送消息並且僅接收一次答案的費用。
如果我在發送第一個數據包之前等待第一個接收超時發生,它似乎可以可靠地工作。
有誰知道為什么第一個UDP數據包永遠不會到達?
這是我在試用中使用的代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using NUnit.Framework;
namespace MulticastTest
{
[TestFixture]
public class Program
{
static void Main(string[] args)
{
new Program().Run();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
[Test]
public void Run()
{
_waitFirstReadTiemout = new AutoResetEvent(false);
IPAddress lMulticastAddress = new IPAddress(0xFAFFFFEF);
IPEndPoint lRemoteEndPoint = new IPEndPoint(lMulticastAddress, 1900);
// Create sender socket
Socket lSendSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp);
// Allow to share the port 1900 with other applications
lSendSocket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress,
true);
// Set TTL for multicast packets: socket needs to be bounded to do this
lSendSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.MulticastTimeToLive,
2);
// Bind the socket to the local end point: this MUST be done before joining the multicast group
lSendSocket.Bind(new IPEndPoint(IPAddress.Loopback, 55236));
// Join the multicast group
lSendSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.MulticastLoopback,
true);
lSendSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.AddMembership,
new MulticastOption(lMulticastAddress));
// Create receiver and start its thread
Thread lReceiveThread = new Thread(ReceiveThread);
lReceiveThread.Start();
int i = 0;
while (!fStop)
{
if (i == 0)
_waitFirstReadTiemout.WaitOne(10000);
byte[] lToSend = Encoding.ASCII.GetBytes(DateTime.Now.ToString("yyyyMMdd HHmmss"));
lSendSocket.SendTo(lToSend, lRemoteEndPoint);
Console.WriteLine("Sent #" + (i + 1) + ": " + DateTime.Now.ToString("yyyyMMdd HHmmss"));
Thread.Sleep(1000);
try
{
if (Console.KeyAvailable || i >= 10)
fStop = true;
}
catch (InvalidOperationException)
{
fStop = i >= 10;
}
finally
{
++i;
}
}
}
private AutoResetEvent _waitFirstReadTiemout;
private bool fStop;
private void ReceiveThread()
{
Socket lSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp);
// Allow to share the port 1900 with other applications
lSocket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress,
true);
// TTL not required here: we will only LISTEN on the multicast socket
// Bind the socket to the local end point: this MUST be done before joining the multicast group
lSocket.Bind(new IPEndPoint(IPAddress.Loopback, 1900));
// Join the multicast group
// If the local IP is a loopback one, enable multicast loopback
lSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.MulticastLoopback,
true);
lSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.AddMembership,
new MulticastOption(
new IPAddress(0xFAFFFFEF)));
lSocket.ReceiveTimeout = 1000;
byte[] lBuffer = new byte[65000];
int i = 0;
while (!fStop)
{
try
{
int lReceived = lSocket.Receive(lBuffer);
++i;
Console.WriteLine("Received #" + i + ": " + Encoding.ASCII.GetString(lBuffer, 0, lReceived));
}
catch (SocketException se)
{
_waitFirstReadTiemout.Set();
Console.WriteLine(se.ToString());
}
}
}
}
}
這很可能是發送線程和接收線程之間的競爭-您在接收者加入組之前發送了第一個數據包。 這解釋了為什么它可以超時。
您可能需要在套接字上啟用環回模式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.