Конференция "Сети" » Обрезается пакет при TCP передаче [WinXP]
 
  • xss22 © (15.11.12 15:31) [0]
    Приветствую!
    Проблема в следующем. При оправке пакета с одного ПК на удаленный ПК, через интернет, пакет обрезается примерно на 1415 байтах.
    Однако по локальной сети - все работает.

    Для передачи данных использую библиотеки от Overbyte.

    А вот и сама передающая процедура:


    procedure TThrdSrvForm.SendTCPToClient(Client : TMyClient; sMs:AnsiString);
    var
     SendRes:integer;
     Ms1, Ms2 :TMemoryStream32;
     i:integer;
    begin
    try
     Ms1:= TMemoryStream32.Create;
     Ms2:= TMemoryStream32.Create;
     Ms1.Size:= Length(sMs);
     move(pointer(sMs)^, Ms1.Memory^, Length(sMs));
     Ms1.Position:=0;
     ztvCompress_StreamToStream(Ms1, Ms2, Ms1.Size, ztvCompressLevel);  //запаковываем  Ms1 в  Ms2
     Ms2.Position:=0;
     SendRes:=Client.Send(Ms2.memory, Ms2.Size);
     SizeOut(SendRes); //отправляем на главную форму размер отправленного пакета
    finally
     Ms1.Free;
     Ms2.Free;
    end;
    end;



    В интернете прочитал:

    Длина дейтаграммы. Это полная длина IP-дейтаграммы (заголовок плюс данные) в байтах. Поскольку размер этого поля равен 16 бит, теоретически максимальный размер IP-дейтаграммы может составлять 65 535 байт. Однако размер дейтаграмм редко превосходит 1500 байт и обычно ограничивается значением 576 байт.


    Неужели в этом кроется проблема??
    Какие решения можете предложить по улучшению кода?
  • xss22 © (15.11.12 15:56) [1]
    а прием пакетов происходит вот так:

    procedure TDataTCP.WSocketDataAvailable(Sender: TObject; ErrCode: Word);
    var
     RecvRes: Integer;
     buffer: array [0..65506] of Byte;
     j,i,k    : LongInt;
     ss:string; //различная строковая информация

     Ms1:TMemoryStream32;
     Ms2:TMemoryStream32;
     sMs:AnsiString;
    begin
    RecvRes := WSocket.Receive(@buffer, SizeOf(buffer));
    if RecvRes <= 0 then Exit;

    try
     try
     Ms1:= TMemoryStream32.Create;
     Ms2:= TMemoryStream32.Create;
     Ms1.WriteBuffer(buffer, RecvRes);  //получен запакованный пакет
     Ms1.Position := 0;
     ztvInflate.ztvDecompress_StreamToStream(Ms1, Ms2, Ms1.Size);  //распаповываем пакет  Ms1 в Ms2
     Ms2.Position := 0;
     SetLength (sMs,Ms2.Size);
     Ms2.Read(sMs[1],Length(sMs));
     except
       log('Ошибка распаковки данных');
     end;
    finally
     Ms1.Free;
     Ms2.Free;
    end;

    end;

  • xss22 © (15.11.12 21:35) [2]
    Помогите! Где ошибки в коде?
  • Сергей М. © (15.11.12 22:25) [3]

    > При оправке ..пакет обрезается


    На оновании чего ты утверждаешь это ?
  • DVM © (15.11.12 22:49) [4]

    > При оправке пакета с одного ПК на удаленный ПК, через интернет,
    >  пакет обрезается примерно на 1415 байтах.
    >

    Ну логично, что данные помещаются в пакеты, меньшие по размеру чем стандартный максимальный размер Ethernet фрейма, но откуда ты узнал размер пакета? Это можно узнать только с помощью снифера.
  • Сергей М. © (15.11.12 23:09) [5]

    > DVM ©   (15.11.12 22:49) [4]


    "Пакетом" он видимо окрестил содержимое отправляемого стрима.

    Если воспринимать его заяву дословно, то "1415" он узрел на главной форме в результате выполнения строчки

    > SizeOut(SendRes)

    что если и вероятно, то для UDP-транспорта, но не для TCP.
  • Slym © (16.11.12 06:06) [6]
    Мама мыла раму. Папа пил пиво.
    Это 2 сообщения. как Ты определил что их тут два? Две точки! (Знак препинания)
    Казнить нельзя помиловать
    Чего не хватает? Запятой! (Знак препинания)
    теперь про твоих баранов

    <------Размер пакета------->
    1различная строковая информа
    ция2различная строковая инфо
    рмация3различная строковая и
    нформация

    как компьютер определит что тут 3 сообщения?
  • xss22 © (16.11.12 08:15) [7]

    >
    > > При оправке ..пакет обрезается
    >
    >
    > На оновании чего ты утверждаешь это ?


    Сервер клиенту отправляет пакет размером 2400 байт.
    Но клиент принимает 1490 байт.
    Размер узнал строчкой RecvRes := WSocket.Receive(@buffer, SizeOf(buffer));
  • xss22 © (16.11.12 08:18) [8]

    > Мама мыла раму. Папа пил пиво.
    > Это 2 сообщения. как Ты определил что их тут два? Две точки!
    >  (Знак препинания)
    > Казнить нельзя помиловать
    > Чего не хватает? Запятой! (Знак препинания)
    > теперь про твоих баранов
    >
    > <------Размер пакета------->
    > 1различная строковая информа
    > ция2различная строковая инфо
    > рмация3различная строковая и
    > нформация
    > как компьютер определит что тут 3 сообщения?


    Ребята, давайте без сарказма.
    Просто помогите пожалуйста исправить вышеуказанный код.
    Согласен, что я делаю не правильно.
    Но я создал эту тему с просьбой о помощи по конкретному моему случаю.
    Надеюсь найдутся добрые люди и помогут исправленным кодом.
    Заранее спасибо!
  • RWolf © (16.11.12 09:27) [9]
    никаких «пакетов» на уровне TCP нет.
    есть соединение, по которому передаётся поток байт до тех пор, пока оно не разорвано.
  • чы (16.11.12 09:35) [10]

    > никаких «пакетов» на уровне TCP нет.
    > есть соединение, по которому передаётся поток байт до тех
    > пор, пока оно не разорвано.


    Да понял что пакеты только у UDP.
    Но в моем случае что не так?
    Почему обрывается??
    И что в коде не так?
  • xss22 © (16.11.12 09:35) [11]
    Помогите исправленным кодом
  • RWolf © (16.11.12 09:44) [12]

    > чы   (16.11.12 09:35) [10]

    почему вы считаете, что оно обрывается?
    в хелпе на WSocket.Receive сказано, что она дожидается разрыва соединения?
    подозреваю, что нет (сам библиотекой от Overbyte не пользуюсь).
  • xss22 © (16.11.12 09:51) [13]

    > почему вы считаете, что оно обрывается?
    > в хелпе на WSocket.Receive сказано, что она дожидается разрыва
    > соединения?
    > подозреваю, что нет (сам библиотекой от Overbyte не пользуюсь).
    >


    Ну потому что я отправляю данные. А приходит только кусок.
  • RWolf © (16.11.12 10:44) [14]
    в общем случае, их и нельзя принять целиком (представьте, что поток данных идёт с веб-камеры).
    к обрыву это не имеет отношения.
  • Сергей М. © (16.11.12 13:10) [15]

    > А приходит только кусок


    Куда приходит-то ?
    Изначально ты заявил что "при отправке", теперь ты заявляешь что "при приеме"..
  • xss22 © (18.11.12 17:02) [16]
    И снова возвращаемся к нашим баранам.
    Проблема в том, что принимающая сторона не приняла весь зашифрованный пакет.
    Для этого нужно при отправке в заголовке указывать 4 байта с размером передаваемого пакета, затем передавать сам пакет.

    Я сделал подобное. Но тут проблема в том, что код не работает.
    И где ж опять ошибка????

    А вот отправляющая:

    procedure TThrdSrvForm.SendTCPToClient(Client : TMyClient; sMs:AnsiString);
    var
     size:integer;
     Ms1, Ms2 :TMemoryStream32;
     i:integer;
    begin
    try
     Ms1:= TMemoryStream32.Create;
     Ms2:= TMemoryStream32.Create;
     DisplayOutTcp('===='+Client.Nick+'===='+FormatDateTime('dd/mm/yyyy(hh:nn:ss)', Now)+'====');
     DisplayOutTcp(sMs); //лог отправленного пакета
     Ms1.Size:= Length(sMs);
     move(pointer(sMs)^, Ms1.Memory^, Length(sMs));
     Ms1.Position:=0;
     ztvCompress_StreamToStream(Ms1, Ms2, Ms1.Size, ztvCompressLevel);  //запаковываем  Ms1 в  Ms2
     Ms2.Position:=0;
     size := Ms2.Size;
     Client.Send(@size, SizeOf(size));
     Client.Send(Ms2.memory, Ms2.Size);
     SizeOut(size); //отправляем на главную форму размер отправленного пакета
    finally
     Ms1.Free;
     Ms2.Free;
    end;
    end;



    вот у меня принимающая процедура:

    procedure TDataTCP.WSocketDataAvailable(Sender: TObject; ErrCode: Word);
    var
     RecvRes: Integer;
     j,i,k    : LongInt;
     ss:string; //различная строковая информация
     Ms1:TMemoryStream32;
     Ms2:TMemoryStream32;
     sMs:AnsiString;
    begin
     RecvRes := WSocket.Receive(@buffer[BufSize], SizeOf(buffer) - BufSize);
     Writeln('recv buf: ', RecvRes);
     if not (RecvRes = INVALID_SOCKET) then BufSize := BufSize + RecvRes; // разрыв соединения и всё такое

     if (BufSize >= 4) then Writeln('packet size: ', PInteger(@buffer)^, ' buf size: ', BufSize - 4);
     if ((BufSize >= 4) and (PInteger(@buffer)^  = BufSize - 4)) then
     begin
     Writeln('ok ');
     try
       try
       Ms1:= TMemoryStream32.Create;
       Ms2:= TMemoryStream32.Create;
       Ms1.WriteBuffer(buffer[4], BufSize - 4);  //получен запакованный пакет
       Ms1.Position := 0;
       ztvInflate.ztvDecompress_StreamToStream(Ms1, Ms2, Ms1.Size);  //распаповываем пакет  Ms1 в Ms2
       Ms2.Position := 0;
       SetLength (sMs,Ms2.Size);
       Ms2.Read(sMs[1],Length(sMs));
       except
         log('Ошибка распаковки данных или записи их в tstrings');
       end;
     finally
       Ms1.Free;
       Ms2.Free;
     end;
     FormMain.fGameEng.vvv(sMs);
     Writeln('ok ');
     BufSize := 0;
     end;
    {
     if RecvRes <= 0 then Exit;
     Exit;  }

    end;

  • Сергей М. © (18.11.12 19:50) [17]

    > код не работает


    И не будет пока не воспользуешься отладчиком.
  • xss22 © (19.11.12 09:28) [18]

    >
    > > код не работает
    >
    >
    > И не будет пока не воспользуешься отладчиком.


    все понятно. один сарказм, а помощи никакой.
    Если не можете или не хотите помочь - тогда просто промолчите
  • Сергей М. © (19.11.12 17:00) [19]
    Да какой сарказм ?
    Суровая правда жизни.
 
Конференция "Сети" » Обрезается пакет при TCP передаче [WinXP]
Есть новые Нет новых   [134435   +8][b:0][p:0.004]