我最近在c#中使用windows app store编程,我遇到了套接字问题。
我需要能够从DataReader()
读取未知长度的数据。
这听起来很简单,但经过几天的搜索后我找不到解决方案。
这是我当前的接收代码(有点草率,需要在我找到解决此问题的方法后进行清理。是的,这有点来自Microsoft的例子)
DataReader reader = new DataReader(args.Socket.InputStream);
try
{
while (true)
{
// Read first 4 bytes (length of the subsequent string).
uint sizeFieldCount = await reader.LoadAsync(sizeof(uint));
if (sizeFieldCount != sizeof(uint))
{
// The underlying socket was closed before we were able to read the whole data.
return;
}
reader.InputStreamOptions
// Read the string.
uint stringLength = reader.ReadUInt32();
uint actualStringLength = await reader.LoadAsync(stringLength);
if (stringLength != actualStringLength)
{
// The underlying socket was closed before we were able to read the whole data.
return;
}
// Display the string on the screen. The event is invoked on a non-UI thread, so we need to marshal
// the text back to the UI thread.
//MessageBox.Show("Received data: " + reader.ReadString(actualStringLength));
MessageBox.updateList(reader.ReadString(actualStringLength));
}
}
catch (Exception exception)
{
// If this is an unknown status it means that the error is fatal and retry will likely fail.
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
{
throw;
}
MessageBox.Show("Read stream failed with error: " + exception.Message);
}
答案 0 :(得分:2)
你走的是正确的行 - 读取第一个INT以找出要发送的字节数。
Franky Boyle是正确的 - 如果没有信令机制,就不可能知道流的长度。这就是为什么它被称为流!
没有套接字实现(包括WinSock)将足够聪明地知道客户端何时完成数据发送。客户可能会在发送数据的过程中喝一杯茶!
您的服务器及其套接字永远不会知道!他们将要做什么?永远等待?我想他们可以等到客户端'关闭'连接?但是你的客户端可能有一个蓝屏,服务器永远不会得到那个TCP关闭数据包,它只会坐在那里认为它有一天会获得更多数据?
我从未使用过DataReader - 我从来没有听过那个类!改为使用NetworkStream。
从我的记忆中,我过去曾编写过这样的代码。我只是打字,没有检查语法。
using(MemoryStream recievedData = new MemoryStream())
{
using(NetworkStream networkStream = new NetworkStream(connectedSocket))
{
int totalBytesToRead = networkStream.ReadByte();
// This is your mechanism to find out how many bytes
// the client wants to send.
byte[] readBuffer = new byte[1024]; // Up to you the length!
int totalBytesRead = 0;
int bytesReadInThisTcpWindow = 0;
// The length of the TCP window of the client is usually
// the number of bytes that will be pushed through
// to your server in one SOCKET.READ method call.
// For example, if the clients TCP window was 777 bytes, a:
// int bytesRead =
// networkStream.Read(readBuffer, 0, int.Max);
// bytesRead would be 777.
// If they were sending a large file, you would have to make
// it up from the many 777s.
// If it were a small file under 777 bytes, your bytesRead
// would be the total small length of say 500.
while
(
(
bytesReadInThisTcpWindow =
networkStream.Read(readBuffer, 0, readBuffer.Length)
) > 0
)
// If the bytesReadInThisTcpWindow = 0 then the client
// has disconnected or failed to send the promised number
// of bytes in your Windows server internals dictated timeout
// (important to kill it here to stop lots of waiting
// threads killing your server)
{
recievedData.Write(readBuffer, 0, bytesReadInThisTcpWindow);
totalBytesToRead = totalBytesToRead + bytesReadInThisTcpWindow;
}
if(totalBytesToRead == totalBytesToRead)
{
// We have our data!
}
}
}