C# Windows Phone 8上的UDP多播组
好的,这是我几天来一直想弄清楚的。我们在WindowsPhone7上有一个应用程序,其中手机加入一个多播组,然后向该组发送和接收消息,以便彼此通话。注意-这是电话对电话的通信 现在,我正在尝试将此应用程序移植到Windows Phone 8—使用Visual Studio 2012中的“转换为Phone 8”功能—到目前为止效果良好。直到我尝试测试电话对电话的通信。手机似乎很好地加入了这个群体,而且它们发送的数据报也很正常。他们甚至会收到发送给群组的信息——然而,没有一部手机会收到来自另一部手机的信息 以下是我的页面后面的示例代码:C# Windows Phone 8上的UDP多播组,c#,sockets,udp,windows-phone-8,datagram,C#,Sockets,Udp,Windows Phone 8,Datagram,好的,这是我几天来一直想弄清楚的。我们在WindowsPhone7上有一个应用程序,其中手机加入一个多播组,然后向该组发送和接收消息,以便彼此通话。注意-这是电话对电话的通信 现在,我正在尝试将此应用程序移植到Windows Phone 8—使用Visual Studio 2012中的“转换为Phone 8”功能—到目前为止效果良好。直到我尝试测试电话对电话的通信。手机似乎很好地加入了这个群体,而且它们发送的数据报也很正常。他们甚至会收到发送给群组的信息——然而,没有一部手机会收到来自另一部手机
// Constructor
public MainPage()
{
InitializeComponent();
}
// The address of the multicast group to join.
// Must be in the range from 224.0.0.0 to 239.255.255.255
private const string GROUP_ADDRESS = "224.0.1.1";
// The port over which to communicate to the multicast group
private const int GROUP_PORT = 55562;
// A client receiver for multicast traffic from any source
UdpAnySourceMulticastClient _client = null;
// Buffer for incoming data
private byte[] _receiveBuffer;
// Maximum size of a message in this communication
private const int MAX_MESSAGE_SIZE = 512;
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
_client = new UdpAnySourceMulticastClient(IPAddress.Parse(GROUP_ADDRESS), GROUP_PORT);
_receiveBuffer = new byte[MAX_MESSAGE_SIZE];
_client.BeginJoinGroup(
result =>
{
_client.EndJoinGroup(result);
_client.MulticastLoopback = true;
Receive();
}, null);
}
private void SendRequest(string s)
{
if (string.IsNullOrWhiteSpace(s)) return;
byte[] requestData = Encoding.UTF8.GetBytes(s);
_client.BeginSendToGroup(requestData, 0, requestData.Length,
result =>
{
_client.EndSendToGroup(result);
Receive();
}, null);
}
private void Receive()
{
Array.Clear(_receiveBuffer, 0, _receiveBuffer.Length);
_client.BeginReceiveFromGroup(_receiveBuffer, 0, _receiveBuffer.Length,
result =>
{
IPEndPoint source;
_client.EndReceiveFromGroup(result, out source);
string dataReceived = Encoding.UTF8.GetString(_receiveBuffer, 0, _receiveBuffer.Length);
string message = String.Format("[{0}]: {1}", source.Address.ToString(), dataReceived);
Log(message, false);
Receive();
}, null);
}
private void Log(string message, bool isOutgoing)
{
if (string.IsNullOrWhiteSpace(message.Trim('\0')))
{
return;
}
// Always make sure to do this on the UI thread.
Deployment.Current.Dispatcher.BeginInvoke(
() =>
{
string direction = (isOutgoing) ? ">> " : "<< ";
string timestamp = DateTime.Now.ToString("HH:mm:ss");
message = timestamp + direction + message;
lbLog.Items.Add(message);
// Make sure that the item we added is visible to the user.
lbLog.ScrollIntoView(message);
});
}
private void btnSend_Click(object sender, RoutedEventArgs e)
{
// Don't send empty messages.
if (!String.IsNullOrWhiteSpace(txtInput.Text))
{
//Send(txtInput.Text);
SendRequest(txtInput.Text);
}
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
SendRequest("start now");
}
//构造函数
公共主页()
{
初始化组件();
}
//要加入的多播组的地址。
//必须在224.0.0.0到239.255.255.255之间
private const string GROUP_ADDRESS=“224.0.1.1”;
//要通过其与多播组通信的端口
私有const int GROUP_PORT=55562;
//来自任何源的多播通信的客户端接收器
UdpAnySourceMulticastClient _client=null;
//传入数据的缓冲区
专用字节[]\u接收缓冲区;
//此通信中消息的最大大小
private const int MAX_MESSAGE_SIZE=512;
已加载专用void PhoneApplicationPage_(对象发送方,路由目标)
{
_client=new-UdpAnySourceMulticastClient(IPAddress.Parse(GROUP\u地址),GROUP\u端口);
_receiveBuffer=新字节[最大消息大小];
_client.beginjoin组(
结果=>
{
_client.EndJoinGroup(结果);
_client.MulticastLoopback=true;
接收();
},空);
}
私有void SendRequest(字符串s)
{
if(string.IsNullOrWhiteSpace)返回;
byte[]requestData=Encoding.UTF8.GetBytes;
_client.BeginSendToGroup(requestData,0,requestData.Length,
结果=>
{
_client.EndSendToGroup(结果);
接收();
},空);
}
私有无效接收()
{
Array.Clear(_receiveBuffer,0,_receiveBuffer.Length);
_client.BeginReceiveFromGroup(_-receiveBuffer,0,_-receiveBuffer.Length,
结果=>
{
点源;
_client.EndReceiveFromGroup(结果,来源外);
stringdatareceived=Encoding.UTF8.GetString(_-receiveBuffer,0,_-receiveBuffer.Length);
string message=string.Format(“[{0}]:{1}”,source.Address.ToString(),dataReceived);
日志(消息,错误);
接收();
},空);
}
私有无效日志(字符串消息,bool ISOUTTING)
{
if(string.IsNullOrWhiteSpace(message.Trim('\0'))
{
返回;
}
//始终确保在UI线程上执行此操作。
部署.Current.Dispatcher.BeginInvoke(
() =>
{
字符串方向=(正在输出)?“>>”:“>”:"我注意到您使用了环回。我认为这意味着当您从客户端发送消息时,您也将收到您发送的消息。这意味着您的接收处理程序将启动。它的效果是以一种似乎不线程安全的方式清除接收缓冲区。尝试在接收方法中放置一些Try-catch,看看是否有任何异常正在发生,但您可能在任何情况下都不使用共享接收缓冲区。您是否尝试加入其他多播组?因为224.0.1.1在IANA分配时似乎正在使用。您可以找到所有的
可能在Windows Phone 8上,某些服务会更严格地侦听传入的消息(例如,在内核模式下运行的网络服务),并且这些消息永远不会转发给您。根据我的经验,UDP多播在Windows Phone 7下的工作非常奇怪,因此您应该在Windows Phone 8上签出相同的功能
以下是我的经验:
检查官方支持的内容,例如在Windows Phone OS 7.1(切换前我尝试的最后一个操作系统)下,支持TCP单播、UDP单播和UDP多播客户端
某些版本的Windows phone只允许在客户端首次打开UDP会话并在不超过10秒内接收到该会话时才允许接收UDP会话,这似乎是Windows phone上的某种安全措施
尝试使用不同的地址:224.0.0.0到224.0.0.255(含)范围内的多播地址是“众所周知的”保留多播地址
在虚拟机和真实的电话设备中进行检查,行为可能会有所不同
我从微软得到的最新评论是,这可能与堆栈中的错误有关。目前我正在等待他们的回复。当我听到更多信息时,我将更新此帖子。但是,如果SendSocketRequest实现的第一行更改为:var stream=waitis,WinRT实现可以正常工作ocket.GetOutputStreamAsync(新的Windows.Networking.HostName(IPAddress.Broadcast.ToString()),GROUP_PORT.ToString());
尝试使用不同的组地址,如“239.0.0.11”.还有微软的消息吗?我遇到了同样的问题,还没有找到解决办法。我也遇到了同样的问题。你有什么新消息吗???@nucleons自从微软确认漏洞在他们的堆栈中后,我没有听到任何其他的消息。我们正在使用我上面描述的解决办法;自从它起作用后,我们已经转移到我们的new工作项。如果我从微软那里听到任何关于此问题解决方案的消息,我会更新此帖子。
// Constructor
public MainPage()
{
InitializeComponent();
}
// The address of the multicast group to join.
// Must be in the range from 224.0.0.0 to 239.255.255.255
private const string GROUP_ADDRESS = "224.0.1.1";
// The port over which to communicate to the multicast group
private const int GROUP_PORT = 55562;
private DatagramSocket socket = null;
private void Log(string message, bool isOutgoing)
{
if (string.IsNullOrWhiteSpace(message.Trim('\0')))
return;
// Always make sure to do this on the UI thread.
Deployment.Current.Dispatcher.BeginInvoke(
() =>
{
string direction = (isOutgoing) ? ">> " : "<< ";
string timestamp = DateTime.Now.ToString("HH:mm:ss");
message = timestamp + direction + message;
lbLog.Items.Add(message);
// Make sure that the item we added is visible to the user.
lbLog.ScrollIntoView(message);
});
}
private void btnSend_Click(object sender, RoutedEventArgs e)
{
// Don't send empty messages.
if (!String.IsNullOrWhiteSpace(txtInput.Text))
{
//Send(txtInput.Text);
SendSocketRequest(txtInput.Text);
}
}
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
socket = new DatagramSocket();
socket.MessageReceived += socket_MessageReceived;
try
{
// Connect to the server (in our case the listener we created in previous step).
await socket.BindServiceNameAsync(GROUP_PORT.ToString());
socket.JoinMulticastGroup(new Windows.Networking.HostName(GROUP_ADDRESS));
System.Diagnostics.Debug.WriteLine(socket.ToString());
}
catch (Exception exception)
{
throw;
}
}
private async void SendSocketRequest(string message)
{
// Create a DataWriter if we did not create one yet. Otherwise use one that is already cached.
//DataWriter writer;
var stream = await socket.GetOutputStreamAsync(new Windows.Networking.HostName(GROUP_ADDRESS), GROUP_PORT.ToString());
//writer = new DataWriter(socket.OutputStream);
DataWriter writer = new DataWriter(stream);
// Write first the length of the string as UINT32 value followed up by the string. Writing data to the writer will just store data in memory.
// stream.WriteAsync(
writer.WriteString(message);
// Write the locally buffered data to the network.
try
{
await writer.StoreAsync();
Log(message, true);
System.Diagnostics.Debug.WriteLine(socket.ToString());
}
catch (Exception exception)
{
throw;
}
finally
{
writer.Dispose();
}
}
void socket_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
try
{
uint stringLength = args.GetDataReader().UnconsumedBufferLength;
string msg = args.GetDataReader().ReadString(stringLength);
Log(msg, false);
}
catch (Exception exception)
{
throw;
}
}