如何在UWP应用程序中读取来自服务器的字节数组



我有一个客户端-服务器应用程序。客户端是HoloLens 2,服务器是在PC上运行的unity。我已经使用HoloLen创建了一个套接字,但我无法读取HoloLen斯上的字节数组。在连接方法中,_inputStream和_outputStream是System.IO.Streams.

PC客户端使用System.Net.Sockets.TcpClientSystem.Net.Sockets.NetworkStream,而UWP(HoloLens(使用Windows.Networking.Sockets.StreamSocket

在ReceiveCallback中,我遇到了int byteLenght = _inputStream.EndRead(result);的问题。当我在HoloLens上尝试此代码时,我得到了异常:";System.ArgumentException:指定的AsyncResult不对应于任何未完成的IO操作";。但我用PC客户端(System.Net.Socket(测试了它,一切都很好。

顺便说一句,我给了所有相关的权限。

如何在UWP应用程序中读取字节数组?

更新:

#if UNITY_EDITOR
private void ConnectUWP(string host, string port)
#else
private async void ConnectUWP(string host, string port)
#endif
{
#if UNITY_EDITOR
errorStatus = "UWP TCP client used in Unity!";
#else
try
{
socket = new Windows.Networking.Sockets.StreamSocket();
Windows.Networking.HostName serverHost = new Windows.Networking.HostName(host);
_receivedData = new Packet();
_receiveBuffer = new byte[DataBufferSize];
await socket.ConnectAsync(serverHost, port);
successStatus = "Connected!";
_outputStream = socket.OutputStream.AsStreamForWrite();
//_streamWriter = new StreamWriter(_outputStream) { AutoFlush = true };

_inputStream = socket.InputStream.AsStreamForRead();
Task.Run(() => StreamToBytes(socket.InputStream));
}
catch (Exception e)
{
errorStatus = e.ToString();
Debugger.GetComponent<TextMeshPro>().text += "n Exception: " + errorStatus;
}
#endif
#if !UNITY_EDITOR
public async Task StreamToBytes(Windows.Storage.Streams.IInputStream stream)
{
using (var reader1 = new Windows.Storage.Streams.DataReader(stream))
{
reader1.InputStreamOptions = Windows.Storage.Streams.InputStreamOptions.ReadAhead;
reader1.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
reader1.ByteOrder = Windows.Storage.Streams.ByteOrder.LittleEndian;
//InBuffer is always 256, 
//even if there is more data waiting. If I put a task.delay in it will always return 25
try
{
await reader1.LoadAsync(256);
}
catch (Exception ex)
{
//..
}
while (reader1.UnconsumedBufferLength > 0)
{
var bytes1 = new byte[reader1.UnconsumedBufferLength];
reader1.ReadBytes(bytes1);
_receivedData.Reset(await HandleData(bytes1));
await reader1.LoadAsync(256); 
}
reader1.DetachStream();
}
}
private async Task<bool> HandleData(byte[] data)
{
int packetLength = 0;
_receivedData.SetBytes(data);
if (_receivedData.UnreadLength() >= 4)
{
// If client's received data contains a packet
packetLength = _receivedData.ReadInt();
if (packetLength <= 0)
{
// If packet contains no data
return true; // Reset receivedData instance to allow it to be reused
}
}
while (packetLength > 0 && packetLength <= _receivedData.UnreadLength())
{
// While packet contains data AND packet data length doesn't exceed the length of the packet we're reading
byte[] packetBytes = _receivedData.ReadBytes(packetLength);

ThreadManager.ExecuteOnMainThread(() =>
{
using (Packet packet = new Packet(packetBytes))
{
int packetId = packet.ReadInt();
_packetHandlers[packetId](packet); // Call appropriate method to handle the packet
}
});
packetLength = 0; // Reset packet length
if (_receivedData.UnreadLength() >= 4)
{
// If client's received data contains another packet
packetLength = _receivedData.ReadInt();
if (packetLength <= 0)
{
// If packet contains no data
return true; // Reset receivedData instance to allow it to be reused
}
}
}
if (packetLength <= 1)
{
return true; // Reset receivedData instance to allow it to be reused
}
return false;
}
#endif

当我在HoloLens上尝试此代码时,我得到了异常:"System.ArgumentException:指定的AsyncResult不对应于任何未完成的IO操作";。

请参阅BeginRead方法文档,在.NET Framework 4及早期版本中,必须使用BeginRead和EndRead等方法来实现异步I/O操作。这些方法在.NET Framework 4.5中仍然可用,以支持遗留代码;但是,新的异步方法,如ReadAsync、WriteAsync、CopyToAsync和FlushAsync,可以帮助您更轻松地实现异步I/O操作我想这个旧的api不能与HoloLens设备兼容,所以请尝试使用ReadAsync来替换,就像下面的一样

byte[] bytes = await StreamToBytes(_inputStream);
public async Task<byte[]> StreamToBytes(Stream stream)
{
byte[] bytes = new byte[stream.Length];
await stream.ReadAsync(bytes, 0, bytes.Length);
stream.Seek(0, SeekOrigin.Begin);
return bytes;
}

或者按照官方使用DataReader读取ReadBytes的处理,更多代码请参阅streamsocket。

更新

using (var reader1 = new DataReader(_inputStream)
{
reader1.InputStreamOptions = Windows.Storage.Streams.InputStreamOptions.Partial;
reader1.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
reader1.ByteOrder = Windows.Storage.Streams.ByteOrder.LittleEndian;
await reader1.LoadAsync(256); //InBuffer is always 256, 
//even if there is more data waiting. If I put a task.delay in it will always return 25
while (reader1.UnconsumedBufferLength > 0)
{
var bytes1 = new byte[reader1.UnconsumedBufferLength];
reader1.ReadBytes(bytes1);
await reader1.LoadAsync(256); 
}
reader1.DetachStream();
}

我为TCP尝试了一切,但使用UWP应用程序的HoloLens几乎不可能实现TCP。所以我尝试了UDP,它运行得很好(https://github.com/mbaytas/HoloLensUDP)。我希望微软在不久的将来为HoloLens 1和2提供一个TCP示例。感谢Nico的帮助。

相关内容

最新更新