Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2008.01.13;
Скачать: [xml.tar.bz2];

Вниз

не доходит значение типа integer   Найти похожие ветки 

 
Dmitry_177   (2007-04-28 22:14) [0]

Использую WinSock, протокол TCP, может ли быть такое что не доходит значение типа integer? Просто так то у меня все работает, но иногда, очень редко бывает что недоходит значение типа integer, причем как-то странно то что именно в одном месте..


 
Dmitrij_K   (2007-04-29 11:45) [1]


> Использую WinSock, протокол TCP, может ли быть такое что
> не доходит значение типа integer?

нет
ошибка в 17-ой строке


 
Belorus ©   (2007-04-29 14:37) [2]

Согласен с Дмитрием.


 
Dmitry_177   (2007-04-29 15:09) [3]

просто у меня как-то странно то что в отладчике я вижу что отправляется, все как надо, а вот на принимающей стороне почему-то приходит число 0, хотя там не 0


 
Dmitrij_K   (2007-04-29 15:56) [4]

Dmitry_177
ищи ошибку в коде
или отправляешь неправильно, или принимаешь или все вместе


 
Dmitry_177   (2007-04-29 16:07) [5]

на отправляющей стороне send(), на принимающей recv(), что здесь может быть неправильного? Я вот думаю то что потом странно как-то происходит, то что последующий вызов select и recv возвращают значение больше чем 0, а на самом деле ничего не отправлялось.. такое ощущение что при отправки этого числа, в буфере уже что-то есть и отправляется уже не число а ерунда.. только я посмотрел насчет этого, то вроде все нормально...((( как можно проверить есть ли данные буфере? или может очищать их как-то?


 
Ketmar ©   (2007-04-29 17:03) [6]

а может вам, барин, сначала почитать умные книги по WinSock и TCP? тогда не будет феерических вопросов типа "может, буфер как-то очистить?"

и настоятельно советую проверить 17-ю строку. она, зараза, часто шибко кривая.


 
DVM ©   (2007-04-30 16:58) [7]

Пиши как отправлял, как принимал - тогда будет видно. Так со слов понять в чем проблема сложно.


 
Сергей М. ©   (2007-05-02 08:34) [8]


> что здесь может быть неправильного?


Неправильным может быть отсутствие в твоем алгоритме анализа результатов, которые эти функции возвращают.


 
Dmitry_177   (2007-05-02 11:26) [9]

Вот сильно упрощенный вариант..
http://slil.ru/24318084
Нужно запустить KLServer.exe, потом KLClient.exe, там прописать свой же IP если сервер запущен на этом же компьютере и нажать "Connect", потом если нажимать много раз "Find"(бывает с и с первого раза, бывает на 20й), бывает выскакивает "1 Ошибка", вот с чем это связано никак не пойму...  Подскажите пожалуйста..


 
Сергей М. ©   (2007-05-02 11:40) [10]


> выскакивает "1 Ошибка", вот с чем это связано никак не пойму


С тем что SelectDataPacket.Code = 0

А вообще код в TForm1.Button2Click просто
жуткий, разбираться в этой "лестнице" нет никакого желания.


 
clickmaker ©   (2007-05-02 11:41) [11]


> [9] Dmitry_177   (02.05.07 11:26)

архив поврежден
Ты бы лучше код показал


 
Dmitry_177   (2007-05-02 11:54) [12]

Выкладываю:

Exchange.pas

unit Exchange;

interface

uses
 Windows;

const
 KL_HELLO               = 111;
 KL_HELLO_OK            = 222;

 KL_FIND                = 001;
 KL_FIND_OK             = 002;
 KL_FIND_NEXT           = 003;

 KL_CHECK               = 100;
 KL_CHECK_OK            = 200;

 KL_EXIT                = 999;

type
 TDataPacket = packed record
   Name: array [0 .. 254] of Char;
   UrAddress: array [0 .. 254] of Char;
   FkAddress: array [0 .. 254] of Char;
   Telephone: array [0 .. 54] of Char;
   Fax: array [0 .. 54] of Char;
   Email: array [0 .. 54] of Char;
   WWWPage: array [0 .. 254] of Char;
   Activity: array [0 .. 254] of Char;
   Director: array [0 .. 254] of Char;
   ContPerson: array [0 .. 254] of Char;
   Bank: array [0 .. 254] of Char;
   INN: array [0 .. 254] of Char;
   SetAccount: array [0 .. 254] of Char;
   CorAccount: array [0 .. 254] of Char;
   BIK: array [0 .. 254] of Char;
   OKPO: array [0 .. 254] of Char;
   Okato: array [0 .. 254] of Char;
   KPP: array [0 .. 254] of Char;
   NContract: array [0 .. 254] of Char;
   LowDate: SYSTEMTIME;
   HightDate: SYSTEMTIME;
   Note: array [0 .. 254] of Char;
 end;

 TSelectDataPacket = packed record
   Name: array [0 .. 254] of Char;
   Code: Longint;
 end;

 TFindDataPacket = packed record
   DataPacket: TDataPacket;
   ContractType: (ctNContract, ctLowDate, ctHightDate, ctNone);
 end;

implementation

end.


 
Dmitry_177   (2007-05-02 11:57) [13]

Блин, слишком длинный код, по частям долго добавлять.. Еще раз залил архив:
http://slil.ru/24318225


 
Сергей М. ©   (2007-05-02 12:37) [14]


> Dmitry_177   (02.05.07 11:26) [9]


Если ты вызовом recv() запросил к чтению N байт и ф-ция возвратила рез-т >= 0, то это вовсе не означает , что приняты запрошенные N байт !!!!


 
Dmitry_177   (2007-05-02 15:02) [15]

а что тогда делать? вызывать заново recv? как тогда мне получить значение типа integer и структуру TSelectDatapacket из этих двух recv-ов?


 
DVM ©   (2007-05-02 15:35) [16]


> а что тогда делать? вызывать заново recv?

во первых она говорит сколько байт реально прочитано, а во вторых в цикле вызывай пока не получишь все.


 
DVM ©   (2007-05-02 15:36) [17]

recv не знает ничего о TSelectDatapacket - она байты принимает


 
Сергей М. ©   (2007-05-02 15:42) [18]


> вызывать заново recv?


Да.


> как тогда мне получить значение типа


Вызывать recv до тех пор, пока не будут получены все данные требуемого размера.


> из этих двух recv-ов


Почему двух ?

Если ты ожидаешь, скажем , SizeOf(Integer)=4 байта, то теоретически может потребоваться от одного до четырех вызовов recv.


 
Dmitry_177   (2007-05-02 15:53) [19]

а как тогда все это склеить? к примеру integer был принят двумя recv-ами, как его склеить в одно?


 
Dmitry_177   (2007-05-02 16:03) [20]

на сколько я понимаю, нужно считывать в какой-то буфер, а как его объявлять? и как потом из него считать тот же integer?


 
Сергей М. ©   (2007-05-02 16:04) [21]


> Dmitry_177   (02.05.07 15:53) [19]


Забудь на время про recv.

Простейший тест на знания Паскаля:

Если у тебя есть, к примеру, есть 4 байта, то как получить из них Integer, если имеющиеся байты следуют в Intel-порядке - от младшего к старшему ?


 
Dmitry_177   (2007-05-02 16:16) [22]

Так?

var
i: integer
Buffer: array of Byte;

SetLength(Buffer, SizeOf(i));
Move(Buffer, i, SizeOf(i));


 
SpellCaster   (2007-05-02 16:30) [23]

Можно и так

var
i: integer
Buffer: array [1..sizeof(integer)] of Byte absolute i;


 
Сергей М. ©   (2007-05-02 16:33) [24]


> Dmitry_177   (02.05.07 16:16) [22]


Ну пусть даже так.

А теперь представь, что буфер Buffer заполняется полученными в рез-те вызовов ф-ции recv данными - первый полученный байт помещается в Buffer[0], второй - в Buffer[1], третий - в Buffer[2], N-ный - в Buffer[N-1] ..


 
Dmitry_177   (2007-05-02 16:37) [25]

мне не очень понятно вот что: вот был вызван recv(KLSock, Buffer, SizeOf(Buffer), 0), вернул он например 2, т.е. было получено 2 байта, как мне потом при вызове следующего recv записать в конец данных в буфере а не в начало, т.е. не на те которые уже были приняты? Вот так: recv(KLSock, Buffer[3], SizeOf(Buffer)-2, 0)?  и как мне реализовать лучше этот цикл? и еще при следующих вызовах recv сколько задавать на получение байт(3 параметр)? так как я уже привел: SizeOf(Buffer)-2?


 
Dmitry_177   (2007-05-02 16:53) [26]

я вот так придумал:

var
 b: bool;
 i: integer;
 iRecv: integer;
 RecvSize: integer;
 Buffer: array of Byte;
begin
 b := false;
 i := 0;
 SetLength(Buffer, SizeOf(iRecv));
 while not b do
   begin
     RecvSize := recv(KLSock, Buffer[i], SizeOf(Buffer), 0);
     if RecvSize = Socket_Error then
       begin
         Break;
         Exit;
       end;
     if RecvSize <> SizeOf(Buffer) then
       begin
         Move(Buffer[i], iRecv, RecvSize);
         i := i + RecvSize;
       end
     else
       b := true;
   end;
end;

Правильно ли так будет или можно как-то проще и лучше?


 
Сергей М. ©   (2007-05-02 16:56) [27]

var
 buf: Pointer;
 BytesNeed: Integer;
 BytresRead: Integer;
 MyData: TMyType; //TMyType м.б. и Integer, и TSelectDataPacket, и что угодно
..

buf := @MyData;
BytesNeed := SizeOf(MyData);
while BytesNeed > 0 do begin
 BytesRead := recv(KLSock, buf^, Min(BytesNeed, SizeOf(buf));
 if BytesRead >= 0 then begin
   Dec(BytesNeed, BytesRead);
   Inc(DWord(buf), BytesRead);
 end else
  ..
end;


 
Dmitry_177   (2007-05-02 17:21) [28]

а как посылать лучше структуру TSelectDataPacket?

send(KLSock, SelectDataPacket, SizeOf(SelectDataPacket), 0)  или надо по кускам?


 
Сергей М. ©   (2007-05-02 17:25) [29]


> или надо по кускам?


Об этом тебе скажет результат вызова send(), точно так же как результат вызова recv() говорит тебе о том, все ли из запрошенного тобой к чтению фактически прочитано.


 
Dmitry_177   (2007-05-02 17:49) [30]

Чтобы каждый раз не мучаться при каждой посылке или приеме информации, я думаю лучше написать функции с этим циклом и уже их использовать.. Вот например с recv:

function NewRecv(s: TSocket; var Buf; len, flags: Integer): Integer;
var
 BytesNeed: Integer;
 BytresWrite: Integer;
begin
 BytesNeed := len;
 while BytesNeed > 0 do
   begin
     BytesRead := recv(s, Buf, BytesNeed, flags);
     if BytesRead = SOCKET_ERROR then
       begin
         Result := SOCKET_ERROR;
         Break;
         Exit;
       end;
     if BytesRead = 0 then
       begin
         Result := len - BytesNeed;
         Break;
         Exit;
       end;
     if BytesRead > 0 then
       begin
         Dec(BytesNeed, BytesRead);
         Inc(DWORD(Buf), BytesRead);
       end;
   end;
 Result := len;
end;

Правильно ли так будет?


 
DVM ©   (2007-05-02 18:07) [31]


> Dmitry_177   (02.05.07 17:49) [30]

я вот так делаю:

function THTTPInputThread.ReadData(ABuffer: TBuffer; BytesExpected: integer): integer;
const
 MaxLen = 262144;
var
 TotalBytesToRead, Found, TotalBytesRead, BytesToRead, BytesRead: integer;
 Rfds: TFDSet;
 TempBuff: array [0..Pred(MaxLen)] of Char;
begin
 FD_ZERO(Rfds);
 FD_SET(Sock, Rfds);
 Found := select(Sock, @Rfds, nil, nil, @FTimeout);
 if Found = 0 then
   begin
     // Select timed out
     Result := -1;
     exit;
   end
 else
   if Found = SOCKET_ERROR then
     begin
       // Select error
       Result := -1;
       exit;
     end;
 TotalBytesToRead := 0;
 if BytesExpected <> 0 then
   begin
     TotalBytesToRead := BytesExpected;
   end
 else
   begin
     if ioctlsocket(Sock, FIONREAD, TotalBytesToRead) = SOCKET_ERROR then
       begin
         // Cannot ioctl()
         Result := -1;
         exit;
       end;
     if TotalBytesToRead = 0  then
       begin
         SocketDisconnect();
         Result := 0;
         exit;
       end;
   end;
 TotalBytesRead := 0;
 repeat
   if TotalBytesToRead > MaxLen then
     BytesToRead := MaxLen
   else
     BytesToRead := TotalBytesToRead;
   ZeroMemory(@TempBuff[0], MaxLen);
   BytesRead := recv(Sock, TempBuff, BytesToRead, 0);
   if BytesRead = SOCKET_ERROR then
     begin
       // Read error
       SocketDisconnect();
       Result := -1;
       exit;
     end
   else
     if BytesRead = 0 then
       begin
         SocketDisconnect();
         Result := 0;
         exit;
       end
     else
       begin
         if ABuffer.Size >= 2097152 then
           begin
             SocketDisconnect();
             Result := -1;
             exit;
           end;
         ABuffer.Append(@TempBuff[0], BytesRead);
         TotalBytesRead := TotalBytesRead + BytesRead;
         TotalBytesToRead := TotalBytesToRead - BytesRead;
       end;
 until TotalBytesToRead <= 0;
 Result := TotalBytesRead;
end;


 
Dmitry_177   (2007-05-03 00:02) [32]

Странно как-то.. Используя тот код который я привел выше, посылаю значение типа integer равное "1", получаю "5"


 
Dmitry_177   (2007-05-03 00:06) [33]

Потом чисто ради эксперимента послал "111", получил "115"


 
Dmitry_177   (2007-05-03 00:20) [34]

как я понял всегда прибавляется на 4.. Наверно это из-за этого: Inc(DWORD(Buf), BytesRead); но эта же строка тоже нужна для того чтобы не в начало буфера записывались последующие вызовы recv.. Что можно с этим сделать?


 
Dmitry_177   (2007-05-03 10:05) [35]

Попробовал вот так:

function KLRecv(s: TSocket; var Buf; len, flags: Integer): Integer;
var
 PBuf: Pointer;   // чтобы двигать ЭТОТ указатель
 BytesNeed: Integer;
 BytesRecv: Integer;
 FDSet: TFDSet;
 TimeOut: TimeVal;
begin
 FD_ZERO(FDSet);
 FD_SET(s, FDSet);
 TimeOut.tv_sec := 60;
 TimeOut.tv_usec := 0;

 PBuf := @Buf;
 BytesNeed := len;
 while BytesNeed > 0 do
   begin
     if select(0, @FDSet, nil, nil, @TimeOut) > 0 then   // чтобы не застопорился на recv
       begin
         BytesRecv := recv(s, PBuf^, BytesNeed, flags);
         if BytesRecv > 0 then
           begin
             Dec(BytesNeed, BytesRecv);
             Inc(DWORD(PBuf), BytesRecv);
           end
         else
           begin
             Result := SOCKET_ERROR;  // это чтобы в самой программе не сверять размер полученных байтов, т.к. всеравно они не все пришли, мне проще сделать это как ошибка SOCKET_ERROR, хоть даже сколько то и было полученно байт..
             Break;
             Exit;
           end;
       end
     else
       begin
         Result := SOCKET_ERROR;   // тоже самое
         Break;
         Exit;
       end;
   end;
Result := len;
end;

и в самой программе:

if KLRecv(KLSock, iRecv, SizeOf(iRecv), 0) <> SOCKET_ERROR then
...

всеравно если посылаю 1 приходит 5, как я понимаю к значению прибавляется размер получаемых данных, т.к. integer 4 байта занимает вот они и прибавляются.. подскажите пожалуйста..



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2008.01.13;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.007 c
2-1197383299
@!!ex
2007-12-11 17:28
2008.01.13
ДОбавить кнопку в кэпшн чюжих окон.


15-1196967066
Light
2007-12-06 21:51
2008.01.13
Вопрос о роуминге


2-1197880874
olegusis
2007-12-17 11:41
2008.01.13
Построение графика функции.


15-1197305271
DillerXX
2007-12-10 19:47
2008.01.13
Ecplise не даёт редактировать


11-1182424519
LazyBob
2007-06-21 15:15
2008.01.13
Некорректный шрифт на KolGroupBox





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский