【发布时间】:2020-09-02 10:17:32
【问题描述】:
我正在开发基于 Unity 的 HoloLens (1) 应用程序。我正在尝试通过 TCP 从基于 Qt 的应用程序 (Windows) 向 HoloLens 发送数据。 Wireshark 显示,我的测试包已被 HoloLens 正确发送和确认。数据以包含消息长度的四个字节开始,紧接着这四个字节开始。在下面的代码中,首先尝试接收四个字节,然后是消息本身。
在客户端应用程序中执行连接和发送数据的代码后,在 HoloLens 上调用StreamSocketListener_ConnectionReceived()。在下一次Update() 调用中,ReadTcpData() 被调用。现在,执行在第一次调用时“停止”
tcpMessageSizeBuffer[tcpMessageSizeBytesRead++] = (byte)stream.ReadByte();
当我尝试越界时,至少调试器会跳出代码。在 catch 块中没有捕获到异常。
如果没有可读取的内容,我期待StreamReader 的EndOfStream 属性为假,因此,当它为真时调用ReadByte 时,我会从流中接收到一个有效字节。我不知道这里出了什么问题。任何提示将不胜感激。
using System;
using System.IO;
using UnityEngine;
#if UNITY_WINRT && !UNITY_EDITOR
using Windows.Networking.Sockets;
using Windows.Networking;
using Windows.Networking.Connectivity;
using Windows.Storage.Streams;
using System.Runtime.InteropServices.WindowsRuntime;
#endif
public class NetworkManager : MonoBehaviour
{
public int tcpPort;
#if UNITY_WINRT && !UNITY_EDITOR
private StreamSocketListener streamSocketListener;
private StreamReader tcpStreamReader = null;
private StreamSocketListenerConnectionReceivedEventArgs connectionArgs;
private DatagramSocket datagramSocket;
private MemoryStream pendingDatagramSocketStream;
#endif
private UInt32 tcpMessageSizeByteCount;
private UInt32 tcpMessageSizeBytesRead;
private byte[] tcpMessageSizeBuffer;
private bool tcpMessageSizeReceived;
private UInt32 tcpMessageByteCount;
private UInt32 tcpMessageBytesRead;
private byte[] tcpMessageBuffer;
// Use this for initialization
void Start()
{
Application.runInBackground = true;
ResetTcpConnection();
}
public void ResetTcpConnection()
{
#if UNITY_WINRT && !UNITY_EDITOR
ResetTcpRead();
if (streamSocketListener != null)
{
tcpStreamReader.Dispose();
tcpStreamReader = null;
connectionArgs = null;
streamSocketListener.Dispose();
streamSocketListener = null;
}
streamSocketListener = new StreamSocketListener();
streamSocketListener.ConnectionReceived += this.StreamSocketListener_ConnectionReceived;
streamSocketListener.BindServiceNameAsync(tcpPort.ToString());
#endif
}
#if UNITY_WINRT && !UNITY_EDITOR
// Process the client connection.
private async void StreamSocketListener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
connectionArgs = args; // Keep this alive
tcpStreamReader = new StreamReader(connectionArgs.Socket.InputStream.AsStreamForRead());
}
#endif
// Update is called once per frame
void Update()
{
#if UNITY_WINRT && !UNITY_EDITOR
if (tcpStreamReader != null && !tcpStreamReader.EndOfStream)
{
Stream stream = tcpStreamReader.BaseStream;
ReadTcpData(ref stream);
}
#endif
}
private void ResetTcpRead()
{
tcpMessageSizeByteCount = sizeof(UInt32);
tcpMessageSizeBytesRead = 0;
tcpMessageSizeBuffer = new byte[tcpMessageSizeByteCount];
tcpMessageSizeReceived = false;
tcpMessageByteCount = 0;
tcpMessageBytesRead = 0;
tcpMessageBuffer = null;
}
private void ReadTcpData(ref Stream stream)
{
try
{
if (!tcpMessageSizeReceived)
{
#if UNITY_WINRT && !UNITY_EDITOR
while(tcpMessageSizeBytesRead < tcpMessageSizeByteCount && !tcpStreamReader.EndOfStream)
{
tcpMessageSizeBuffer[tcpMessageSizeBytesRead++] = (byte)stream.ReadByte();
}
if(tcpMessageSizeBytesRead == tcpMessageSizeByteCount)
{
tcpMessageByteCount = BitConverter.ToUInt32(tcpMessageSizeBuffer, 0);
}
#endif
if (tcpMessageByteCount > 0)
{
tcpMessageBuffer = new byte[tcpMessageByteCount];
tcpMessageSizeReceived = true;
}
}
else
{
// Read the message
int bytesToRead = (int)(tcpMessageByteCount - tcpMessageBytesRead);
bytesToRead = bytesToRead > 10000 ? 10000 : bytesToRead;
int bytesRead = stream.Read(tcpMessageBuffer, (int)tcpMessageBytesRead, bytesToRead);
tcpMessageBytesRead += (uint)bytesRead;
// Did we finish reading the message?
if (tcpMessageBytesRead >= tcpMessageByteCount)
{
ResetTcpRead();
}
}
}
catch (Exception e)
{
throw e;
}
}
}
【问题讨论】: