Я пытаюсь отправить все плитки (которые называются Частицами, не путайте их с эффектами частиц клиента) в моем мире (массив 2D размером 500x350 в моем классе World) через NetworkStream, подключенный к моему Клиенту ина сервере и стороне клиента.
Код выглядит следующим образом:
public int ServerSendWorldData(NetworkStream networkStream, Point from, Point size, bool reportBytesSent, Networking.Client toClient)
{
int bytesOfAcknowledgementSent = 0;
int totalBytesSent = 0;
int tilesSentThisAcknowledgement = 0;
int tilesToSendForThisAcknowledgement = 20;
for (int x = from.X; x < size.X; x++)
{
for (int y = from.Y; y < size.Y; y++)
{
Thread.Sleep(0);
//Handle acknowledgement if needed.
if (tilesSentThisAcknowledgement >= tilesToSendForThisAcknowledgement)
{
//Wait for Client acknowledgement.
bytesOfAcknowledgementSent += Networking.NetworkingHelp.SendMessageFromByte((byte)Networking.MessageType.ServerSendWorldMapDataWaitAcknowledgement, networkStream);
//Handle here.
if (networkStream.ReadByte() == (byte)Networking.MessageType.ClientAcknowledgeWorldMapData)
tilesSentThisAcknowledgement = 0;
else
throw new Exception("Client did not acknowledge data!");
}
if (world.worldParticles[x, y] != null)
{
//Send Particle Data
totalBytesSent += Networking.NetworkingHelp.SendMessageFromByte((byte)Networking.MessageType.ServerSendWorldMapDataParticle, networkStream);
totalBytesSent += Networking.NetworkingHelp.SendMessageFromInt(x, networkStream);
totalBytesSent += Networking.NetworkingHelp.SendMessageFromInt(y, networkStream);
totalBytesSent += Networking.NetworkingHelp.SendMessageFromInt(world.worldParticles[x, y].ID, networkStream);
//totalBytesSent += Networking.NetworkingHelp.SendMessageFromInt(world.worldParticles[x, y].spriteIndex, networkStream);
totalBytesSent += Networking.NetworkingHelp.SendMessageFromBool(world.worldParticles[x, y].draw, networkStream);
totalBytesSent += Networking.NetworkingHelp.SendMessageFromBool(world.worldParticles[x, y].collisionWithEntities, networkStream);
tilesSentThisAcknowledgement++;
}
}
}
if (reportBytesSent)
{
Statistics.Console.WriteLine("Sent " + totalBytesSent + " bytes of World data to Client " + toClient.name + " and " + bytesOfAcknowledgementSent + " bytes of acknowledgement was exchanged!");
}
return totalBytesSent;
}
Класс NetworkingHelp в основном просто networkStream.Write с помощью BitConverter, преобразующего данные, такие как целые числа в байты, или кодировкупреобразование данных, таких как строки, в байты в UTF8.
Код отправляет клиенту в общей сложности 0,76 МБ картографических данных.
При подключении к серверу у меня нет проблемы.используя localhost / IPAddress.Loopback, но проблема возникает при отправке данных Клиентам через Интернет - данные отправляются крайне медленно (вероятно, из-за размера файла, хотя я не уверен) и без бита кода «Обработка подтверждения»...
//Handle acknowledgement if needed.
if (tilesSentThisAcknowledgement >= tilesToSendForThisAcknowledgement)
{
//Wait for Client acknowledgement.
bytesOfAcknowledgementSent += Networking.NetworkingHelp.SendMessageFromByte((byte)Networking.MessageType.ServerSendWorldMapDataWaitAcknowledgement, networkStream);
//Handle here.
if (networkStream.ReadByte() == (byte)Networking.MessageType.ClientAcknowledgeWorldMapData)
tilesSentThisAcknowledgement = 0;
else
throw new Exception("Client did not acknowledge data!");
}
... Клиент получает около 20 тайлов мира и выбрасывает«Невозможно записать данные в транспортное соединение: существующее соединение было принудительно закрыто удаленным хостом», это происходит потому, что Клиент получает 1-байтовое сообщение с байтом 0 в качестве содержимого.
Кажется,что пауза, создаваемая кодом «Подтверждение дескриптора», решает эту проблему, но делает передачу данных в мире намного медленнее.
Помощь будет высоко ценится, и я знаю, что мой код немного запутан (открытна предложения о том, как его улучшить, я впервые отправляю столько данных).Вот блок кода для чтения конкретного сообщения для Клиента.
//WorldParticlesMapDataParticle
else if (recievedMessage[0] == (byte)Networking.MessageType.ServerSendWorldMapDataParticle)
{
//Read the position of the new data.
recievedMessageBytes = networkStream.Read(recievedMessage, 0, 4);
int newParticleX = BitConverter.ToInt32(recievedMessage, 0);
recievedMessageBytes = networkStream.Read(recievedMessage, 0, 4);
int newParticleY = BitConverter.ToInt32(recievedMessage, 0);
//Read the particle ParticleID.
recievedMessageBytes = networkStream.Read(recievedMessage, 0, 4);
int newParticleID = BitConverter.ToInt32(recievedMessage, 0);
//Read the particle SpriteID.
//recievedMessageBytes = networkStream.Read(recievedMessage, 0, 4);
//int newSpriteID = BitConverter.ToInt32(recievedMessage, 0);
//Read the particle draw.
recievedMessageBytes = networkStream.Read(recievedMessage, 0, 1);
bool newParticleDraw = BitConverter.ToBoolean(recievedMessage, 0);
//Read the particle collision.
recievedMessageBytes = networkStream.Read(recievedMessage, 0, 1);
bool newParticleCollision = BitConverter.ToBoolean(recievedMessage, 0);
//Set particle.
try
{
world.worldParticles[newParticleX, newParticleY] = World.Particle.ParticleManager.particleArray[newParticleID];
//world.worldParticles[newParticleX, newParticleY].spriteIndex = newSpriteID;
world.worldParticles[newParticleX, newParticleY].draw = newParticleDraw;
world.worldParticles[newParticleX, newParticleY].collisionWithEntities = newParticleCollision;
}
catch (Exception ex)
{
Statistics.Console.WriteLine("Server requested new Particle at " + newParticleX + "," + newParticleY + ", but Client failed to place it due to an exception : " + ex.Message);
try
{
world.worldParticles[newParticleX, newParticleY] = null;
}
catch
{ }
}
}