Ada*_*art 55 c# sockets udp datagram windows-phone-8
好的,这是我一直试图弄清楚几天的.我们在Windows Phone 7上有一个应用程序,其中电话加入多播组,然后向该组发送和接收消息以相互通信.注意 - 这是电话到电话的通信.
现在,我正在尝试将此应用程序移植到Windows Phone 8 - 使用Visual Studio 2012中的"转换为电话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");
}
Run Code Online (Sandbox Code Playgroud)
为了简单地测试UDP堆栈,我从这里找到的MSDN下载了样本,并在一对Windows Phone 7设备上测试了它,它按预期工作.然后我转换到Windows Phone 8并部署到我的手机,设备似乎再次发起连接,用户可以输入他们的名字.但是,设备再次无法查看或与其他设备通信.
最后,我使用新的DatagramSocket实现实现了一个简单的通信测试,我再次看到成功启动,但没有设备间通信.
这与使用数据报套接字实现的页面后面的代码相同:
// 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;
}
}
Run Code Online (Sandbox Code Playgroud)
昨晚我带着手机回家在我的家庭无线网络上进行测试,很低,看到我得到了成功的设备通信.
所以回顾一下 - 我的遗留Windows Phone 7代码在我的工作网络上运行良好.Windows Phone 8的端口(无实际代码更改)不会发送设备间通信.此代码适用于我的家庭网络.代码在附加调试器的情况下运行,并且在执行期间没有任何错误或异常的迹象.
我正在使用的手机是:
Windows Phone 7 - Nokia Lumia 900(*2),Nokia Lumia 800(*3)Windows Phone 8 - Nokia Lumia 920(*1),Nokia Limia 820(*2)
这些都运行最新的操作系统,并处于开发人员模式.开发环境是运行Visual Studio 2012 Professional的Windows 8 Enterprise
我无法告诉你很多关于无线网络的工作 - 除了Phone 7设备没有问题.
至于我使用的家庭无线网络,这只是一个基本的BT宽带路由器,没有改变"开箱即用"的设置.
显然,配置两个网络的方式存在问题,但Windows Phone 8实现UDP消息的方式也存在很明显的问题.
任何输入都会受到赞赏,因为这让我很生气.
小智 1
我注意到你使用了环回。我认为这意味着当您从客户发送消息时,您也会收到您发送的消息。这意味着您的接收处理程序将触发。它具有以看似非线程安全的方式清除接收缓冲区的效果。尝试在您的接收方法中放入一些 try catch 并查看是否发生任何异常情况,但您可能在任何情况下都不使用共享接收缓冲区。