Поскольку вы еще не опубликовали код для демонстрации своей реализации TCP-сервера или клиента, я могу только строить догадки и пытаться объяснить, что здесь может происходить .
Это означает, чтоПотенциальные проблемы и решения, которые я излагаю ниже, могут относиться или не относиться к вам, но, несмотря на это, эта информация по-прежнему может быть полезна для тех, кто может найти этот вопрос в будущем.
TL; DR: (скорее всего) Сервер либо слишком медленный, либо сервер неправильно ожидает буферизации полных «tcp-пакетов», либо сервер не знает, когда нужно правильно запускаться и останавливаться, и выполняет синхронизациюв то время как он ожидает того, что он считает «полным пакетом», как определено чем-то вроде размера буфера.
Мне кажется, что вы отправляете данные с клиента либо быстрее, чем сервер, который сервер может прочитать,или, более вероятно, сервер буферизует установленное число байтов из текущего TCP Stream
и ожидает заполнения буфера перед выводом additioнальные данные.
Если вы отправляете это через localhost
, то вряд ли вы приблизитесь к пределу потока, хотя, и я ожидаю, что сервер, написанный на C ++, сможет не отставать от клиента javascript,
Так что это наводит меня на мысль, что проблема в действительности заключается в буфере потока на стороне C ++.
Теперь, поскольку у сервера нет возможности узнать, какие данные вы отправляете и какбольшую часть этого вы отправляете, для потока TCP обычно используется буфер потока, который непрерывно считывает данные из сокета, пока либо буфер не заполнится до известного размера, либо пока он не увидит предопределенный «символ остановки».Обычно это может быть что-то вроде «конца строки» или \n
символа, иногда \n\r
(перевод строки, перевод каретки) в зависимости от вашей операционной системы.
Поскольку вы не указали, как вы получаетеваши данные, я просто предположу, что вы создали буфер char
или byte
определенного размера.Я довольно сильно заболел информацией о сокетах C ++, поэтому могу ошибаться, но я верю, что по умолчанию для потоков Tcp C ++ есть тайм-аут чтения по умолчанию.
Это означает, что вы, возможно, сталкиваетесь с 1из 2 вопросов.
Ситуация 1) Вы ждете, пока этот буфер byte
/ char
не будет заполнен, прежде чем выводить свои данные.Проблема в том, что он будет действовать как автобус, который покидает станцию, только когда все места заполнены.Если вы не заполняете все места, ваш сервер просто сидит и ждет, пока он не получит больше данных, чтобы полностью заполнить и вывести ваши данные.
Ситуация 2) Вы столкнулись с таймаутом чтения сокета ипоэтому функция не получает все данные перед выводом данных.Это как автобус, который ходит по часам.Каждые 10 минут этот автобус покидает станцию, не имеет значения, заполнен он или пуст, он уходит, и следующий автобус заберет всех, кто опоздает.В вашем случае поток TCP не может загрузить 1, 2 and 3
на шину достаточно быстро, поэтому шина уходит с 1, 2
, потому что после 20 мс не получая данных, сервер выходит из функции и выводитданные.В следующем цикле, однако, 3
ожидает вверху потокового буфера, готового к выходу на следующую шину.Поток загрузит 3
, подождет до тех пор, пока эти 20 мс не закончатся, а затем выйдет, прежде чем повторить этот цикл.
Я думаю, что, скорее всего, возникнет первая ситуация, так как я ожидаю, что сервер либо начнет догонять, либо отстает, поскольку 2 сервера либо начинают синхронизироваться вместе, либо имеют внутренний буфер потока TPCЗаполните, когда сервер все больше и больше отстает.
Главное здесь, , вам нужен какой-то способ синхронизации клиентских и серверных соединений .Я бы рекомендовал отправлять «начальный байт» и «конечный байт» в одиночное состояние, когда сообщение начинается и заканчивается, чтобы вы не выходили из функции слишком рано.
Или отправьте начальный байт, за которым следует размер пакета в байтах, затем заполняйте буфер до тех пор, пока в вашем буфере не будет правильное количество байтов.Кроме того, вы можете включить конечный байт также для некоторой базовой проверки ошибок.
Это довольно сложная тема, и трудно действительно дать вам хороший ответ без какого-либо кода от вас, но это также должно помочь любому вбудущее, которое может иметь аналогичную проблему.
РЕДАКТИРОВАТЬ Я вернулся и перечитал ваш вопрос и заметил, что вы сказали, что это было только с большими объемами данных , поэтому я думаю, что мое первоначальное предположение было неверным,и это более вероятная ситуация 2 , потому что клиент отправляет данные на ваш сервер быстрее, чем сервер может их прочитать, и, таким образом, это может быть бутылочным взломом соединения, и клиент сможет отправлять дополнительные данные только один разСервер освободил часть своего буфера потока TCP.
Думайте об этом как о трубе с водой.Гнездо (трубка) может принимать (заполнять) только таким количеством данных (воды), прежде чем заполнится.Как только вы дадите немного воды на дно, вы можете заполнить ее немного больше.Единственная причина, по которой он работает для маленьких файлов, заключается в том, что файл слишком мал, чтобы заполнить всю трубу.
Дополнительные мысли: Вы можете увидеть, как я подходил к этой проблеме в C # в этом вопросе: Непрерывное чтение с последовательного порта должным образом
И еще один похожий вопрос, который у меня был ранее (снова в C #): Как использовать Task.WhenAny с ReadLineAsync для получения данных из любого TcpClient
Прошло некоторое время с тех пор, как я поиграл с TCP-потоками, поэтому я приношу свои извинения за то, что я не помню всех деталей ниши и предостережений из протокола, но, надеюсь, этой информации достаточно, чтобы получитьВы в центре событий для решения своей проблемы.
Полный отказ от ответственности, прошло более 2 лет с тех пор, как я в последний раз касался сокетов TCP C ++, и с тех пор работал с сокетами / веб-сокетами на других языках (таких как C #и JavaScript), поэтому у меня могут быть некоторые факты неправильные о поведении C ++ TCP-сокетов, в частности, но основная информацияна все еще должно применяться.Если я ошибаюсь, кто-то в комментариях, скорее всего, будет иметь правильную информацию.
Наконец, добро пожаловать в переполнение стека!