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

Форум администраторов игровых серверов (https://forum.zone-game.info/TT.php)
-   Программирование / Programming (https://forum.zone-game.info/forumdisplay.php?f=98)
-   -   Чтение из сокета (https://forum.zone-game.info/showthread.php?t=39344)

Zubastic 12.10.2015 03:05

Чтение из сокета
 
Собственно пришел к тому, что код, который был у меня написан неэффективен, и как следствие тормозит все. Другое дело, что я понятия не имею, как переписать этот кусок:
            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();
                }
            }
Code: C++
Собирать пакет по 1 байту мне кажется глупым занятием, хотя возможно я не прав и это решение оптимально...вообщем буду рад комментариям.

n3k0nation 12.10.2015 04:23

Re: Чтение из сокета
 
Наркоман :D
У тебя должен быть буфер допустим 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);
                        }
                }


Zubastic 12.10.2015 12:54

Re: Чтение из сокета
 
Мопед не мой, я только его чиню :redlol:
https://code.google.com/p/l2script/s...g/TCPClient.cs
Цитата:

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

silvermain 12.10.2015 14:54

Re: Чтение из сокета
 
Цитата:

Сообщение от Zubastic (Сообщение 401333)
Мопед не мой, я только его чиню :redlol:
https://code.google.com/p/l2script/s...g/TCPClient.cs

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

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

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

Zubastic 12.10.2015 15:11

Re: Чтение из сокета
 
Цитата:

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

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

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

Добавлено через 17 минут
Переписал вот так:
                    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;
Code: C++
В итоге имеем фризы и очень долгую загрузку гирана....

silvermain 12.10.2015 16:20

Re: Чтение из сокета
 
Спойлер:
Свернуть ↑Развернуть ↓


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

вот, самый простой обмен пакетами, можно перепилить легко...
1:
Свернуть ↑Развернуть ↓


5 минут на коленке....

Zubastic 12.10.2015 16:48

Re: Чтение из сокета
 
Остановился на этом:
        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();
                }
            }
        }
Code: C++

William008 04.03.2016 08:19

Re: Чтение из сокета
 
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


Текущее время: 21:11. Часовой пояс GMT +3.

Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot