Форум администраторов игровых серверов

Полная версия: Чтение из сокета
Вы просматриваете упрощённую версию нашего контента. Просмотр полной версии с полным форматированием.
Собственно пришел к тому, что код, который был у меня написан неэффективен, и как следствие тормозит все. Другое дело, что я понятия не имею, как переписать этот кусок:
[SRC="c++"] while (Connected)
{
try
{
var tmpbuffer = new byte[1];
SocketToServer.Receive(tmpbuffer, 1, SocketFlags.None);
var newBuffer = new byte[_bufferFc.Length + 1];
_bufferFc.CopyTo(newBuffer, 0);
newBuffer[_bufferFc.Length] = tmpbuffer[0];
var packetLength = -1;
if (newBuffer.Length > 1) packetLength = BitConverter.ToInt16(new[] { newBuffer[0], newBuffer[1] }, 0);
if (newBuffer.Length >= packetLength && packetLength != -1)
{
var finalPacket = new byte[packetLength];
var leftOver = new byte[newBuffer.Length - packetLength];
newBuffer.CopyTo(finalPacket, 0);
newBuffer.CopyTo(finalPacket, newBuffer.Length - packetLength);
newBuffer = leftOver;
DataReceivedToClient(finalPacket);
_dbg.Information(finalPacket.Length + " Fc: " + BitConverter.ToString(finalPacket));
}
_bufferFc = newBuffer;
}
catch
{
Close();
}
}[/SRC]

Собирать пакет по 1 байту мне кажется глупым занятием, хотя возможно я не прав и это решение оптимально...вообщем буду рад комментариям.
Наркоман Big Grin
У тебя должен быть буфер допустим 16кб, ты в него принимаешь данные. Лимит буфера (сколько мы записали в буфер) возвращается методом receive. Собираем из первых 2х байт длину пакета (если ладва). Если пакет весь в буфере, то копируем нужные данные, если пакет не полностью в буфере, то делаем новый буфер и сохраняем данные у объекта клиента.

Пример на джаве:
Код:
                SocketChannel channel = client.getChannel();
                if(!channel.isOpen()) {
                    continue;
                }
                
                ByteBuffer buffer = client.getReadBuffer();
                if(buffer == null) {
                    buffer = directBuffer;
                } else if(!buffer.hasRemaining()) {
                    NetHelper.closeClient(client);
                    client.setReadBuffer(null);
                    bufferCache.put(buffer);
                    continue;
                }
                
                try {
                    channel.read(buffer);
                } catch (IOException e) {
                    NetHelper.closeClient(client);
                    continue;
                }
                
                buffer.flip();
                getListener().onReadClient(client, buffer);
                
                if(buffer.hasRemaining()) {
                    buffer.compact();
                    if(buffer.isDirect()) {
                        buffer = bufferCache.get();
                        buffer.put(directBuffer);
                        client.setReadBuffer(buffer);
                        directBuffer.clear();
                    }
                } else if(!buffer.isDirect()) {
                    client.setReadBuffer(null);
                    bufferCache.put(buffer);
                } else {
                    directBuffer.clear();
                }

Код:
        int pos = 0;
        for(;;) {
            if(!buffer.hasRemaining()) {
                return;
            }
            
            int pSize = header.readSize(buffer, pos);
            if(pSize > buffer.capacity() || pSize < header.getBytes() + header.getOpcodeBytes()) {
                NetHelper.closeClient(client);
                return;
            }
            
            if(pSize > buffer.remaining()) {
                return;
            }
            
            byte[] wrap = new byte[pSize];
            buffer.position(pos);
            buffer.get(wrap);
            pos += pSize;
            buffer.position(pos);
            
            ByteBuffer packetBuffer = Buffers.allocHeap(wrap);
            if(nextProcessor != null) {
                nextProcessor.onReadClient(processor, client, packetBuffer);
            }
        }
Мопед не мой, я только его чиню :redlol:
https://code.google.com/p/l2script/sourc...PClient.cs
Цитата:У тебя должен быть буфер допустим 16кб, ты в него принимаешь данные. Лимит буфера (сколько мы записали в буфер) возвращается методом receive. Собираем из первых 2х байт длину пакета (если ладва). Если пакет весь в буфере, то копируем нужные данные, если пакет не полностью в буфере, то делаем новый буфер и сохраняем данные у объекта клиента.
Я пытался это сделать...получил коррапченные длинные пакеты. Вообщем сегодня попробую дубль два, благо я еще разнес логику в 3 потока (получение + декрипт), обработка (крипт + отправка обратно).
Zubastic Написал:Мопед не мой, я только его чиню :redlol:
https://code.google.com/p/l2script/sourc...PClient.cs

Я пытался это сделать...получил коррапченные длинные пакеты. Вообщем сегодня попробую дубль два, благо я еще разнес логику в 3 потока (получение + декрипт), обработка (крипт + отправка обратно).

больше на велосипед с моторчиком смахивает.....)))

Если уж делать что либо, то лучше писать с нуля самим... а переделывать или доделывать то, что было сделано другими, долгое и мутное занятие.....
silvermain Написал:больше на велосипед с моторчиком смахивает.....)))

Если уж делать что либо, то лучше писать с нуля самим... а переделывать или доделывать то, что было сделано другими, долгое и мутное занятие.....
Ты не поверишь сколько я уже там переписал Big Grin
Лично мне проще взять что-то готовое и допиливать под себя, чем начинать с нуля. Не могу я в структуру ибо у меня один спагетти код получается Sad

Добавлено через 17 минут
Переписал вот так:
[SRC="c++"] var tmpbuffer = new byte[65536];
var len = SocketToClient.Client.Receive(tmpbuffer, SocketFlags.None);
var newBuffer = new byte[_bufferToClient.Length + len];
Array.Copy(_bufferToClient, newBuffer, _bufferToClient.Length);
Array.Copy(tmpbuffer, 0, newBuffer, _bufferToClient.Length, len);
if (newBuffer.Length > 1)
{
var packetLength = BitConverter.ToInt16(new[] { newBuffer[0], newBuffer[1] }, 0);
if (newBuffer.Length >= packetLength)
{
var inputPacket = new byte[packetLength];
var leftOver = new byte[newBuffer.Length - packetLength];
Array.Copy(newBuffer, inputPacket, packetLength);
Array.Copy(newBuffer, packetLength, leftOver, 0, newBuffer.Length - packetLength);
newBuffer = leftOver;
_readFromClient.Add(inputPacket);
//_dbg.Information("[ReadFromServer] Raw Packet:" + BitConverter.ToString(inputPacket));
//new Thread(() => DataReceivedFc(ref finalPacket)).Start();
}
}
_bufferToClient = newBuffer;[/SRC]
В итоге имеем фризы и очень долгую загрузку гирана....
Спойлер

во первых, слишком много всего.... во вторых, буфер часом не велик?=)))

вот, самый простой обмен пакетами, можно перепилить легко...
1

5 минут на коленке....
Остановился на этом:
[SRC="c++"] private void TcpListenToClient()
{
var offset = 0;
var buffer = new byte[16384];
Connected = SocketToClient.Connected;
while (Connected)
{
try
{
offset += SocketToClient.GetStream().Read(buffer, offset, 16384 - offset);
var packetLength = BitConverter.ToInt16(new[] {buffer[0], buffer[1]}, 0);
while (offset >= packetLength && packetLength > 0)
{
var inputPacket = new byte[packetLength];
offset -= packetLength;
Array.Copy(buffer, 0, inputPacket, 0, packetLength);
Array.Copy(buffer, packetLength, buffer, 0, 16384 - packetLength);
_readFromClient.Add(inputPacket);
_dbg.Information("[ReadFromClient] Raw Packet:" + BitConverter.ToString(inputPacket));
packetLength = BitConverter.ToInt16(new[] {buffer[0], buffer[1]}, 0);
}
}
catch
{
Close();
}
}
}[/SRC]
more on a bike with an engine looks like ) If we accomplish something, it is best to compose sans preparation yourself ... what's more, to redesign or complete what has been finished by others, long and dull lesson