Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.01.13;
Скачать: CL | DM;

Вниз

не доходит значение типа 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;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.07 c
15-1196879629
@!!ex
2007-12-05 21:33
2008.01.13
Темы для XP


3-1188949392
kalan
2007-09-05 03:43
2008.01.13
Использование Oracle и InterBase в одном приложении


2-1197050465
Igor Zorkov
2007-12-07 21:01
2008.01.13
Подскажите как обработать событие OnClick пункта меню


3-1189077558
Farel
2007-09-06 15:19
2008.01.13
Remote locate base


15-1197234318
Acka
2007-12-10 00:05
2008.01.13
Английский технический текст на 10 тысяч символов