Я пишу UDP-сервер и хочу уменьшить количество распределений, которые происходят для входящих и исходящих пакетов датаграмм. Одна из вещей, которую я хотел бы сделать, - это повторно использовать потоки, которые я выделяю для чтения и записи моих пакетов датаграмм.
У меня есть этот метод, который использует экземпляр BinaryReader
при получении пакетов для чтения буфера на объект-экземпляр.
// Simplified version of the receive data method.
private void ReceiveClientData(IAsyncResult result)
{
int receivedData = socket.EndReceiveFrom(result, ref endPoint);
if (receivedData == 0)
{
this.ListenForData(socket);
return;
}
// Read the header in from the buffer first so we know what kind of message and how to route.
this.binaryReader.BaseStream.SetLength(receivedData);
this.binaryReader.BaseStream.Seek (0, SeekOrigin.Begin);
// Can't reset the MemoryStream buffer to the new packet buffer.
// How does this get consumed by the stream without allocating a new MemoryStream(buffer)?
byte[] buffer = (byte[])result.AsyncState;
// Deserialize the bytes into the header and datagram.
IClientHeader header = new ClientHeader();
header.GetMessageFromBytes(this.binaryReader);
IClientDatagram datagram = this.datagramFactory.CreateDatagramFromClientHeader(header);
datagram.GetMessageFromBytes(this.binaryReader);
this.ListenForData(socket);
}
Безопасно ли повторно использовать тот же BinaryReader
и лежащий в основе MemoryStream
, возвращая I Seek к началу потока? После некоторого чтения может показаться, что Socket не будет читать и писать пакеты одновременно, что потребовало бы от меня использования Stream
на вызов EndReceiveFrom
. Похоже, вы можете выполнять каждую операцию одновременно, например, чтение + запись, но не одновременное чтение или одновременную запись. Из-за этого я бы подумал, что смогу повторно использовать ридер, но я не уверен, что смогу. Для этого мне пришлось бы предоставить MemoryStream
новый буфер для чтения. Можете ли вы это сделать, или мне нужно создавать новый MemoryBuffer
для каждого нового пакета, полученного из сокета?
Я хотел бы применить тот же подход к отправке пакетов обратно клиенту. Для этого я попытался установить длину моего MemoryStream
на 0 и вернуться к началу. Похоже, это не очищает буфер, как описано в другом ответе здесь. Я все еще вижу данные старого буфера в t
ниже.
public void SendMessage(IServerDatagram message)
{
this.binaryStream.Seek(0, SeekOrigin.Begin);
this.binaryStream.SetLength (0);
// Contains old buffer data.
var t = this.binaryStream.GetBuffer ();
message.Serialize (this.binaryWriter);
// Contains a mixture of new bytes + old bytes.
byte[] data = this.binaryStream.GetBuffer();
this.binaryWriter.Flush ();
// Send the datagram packet.
this.udpServerSocket.SendTo(data, this.connectedClients.FirstOrDefault().Key);
}
Я не знаю заранее, насколько большим должен быть буфер, поэтому я не могу SetLength
соответствовать размеру моего нового буфера. Нет ли другого способа повторно использовать Stream без необходимости создавать новый для каждого сообщения? Если я отправляю тысячи сообщений в секунду, это может вызвать некоторую нехватку памяти, не так ли?