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

Вниз

На отправляющий сокет приходит инфа, хотя приходить не должна...   Найти похожие ветки 

 
3APA3A ©   (2004-03-25 22:09) [0]

Объясните мне, пожалуйста, следующее
 создаю сокет
 var sock : Integer;
     lWSA : WSADATA;
     local, remote : sockaddr_in;
     data : Cardinal;
 begin
   WSAStartup(MakeWord(1, 1), lWSA);    
   sock := socket(AF_INET, SOCK_DGRAM, 0);
   local.sin_family := AF_INET;
   local.sin_port := 55000;
   local.sin_addr.s_addr := inet_addr("local ip");
   bind(sock, local, sizeof(local));
   
   remote.sin_family:=AF_INET;
   remote.sin_port:=60000;
   remote.sin_addr.s_addr:=inet_addr("remote ip");  
   
   sendto(sock, data, 4, 0, remote, sizeof(remote));

   n:=sizeof(remote);
   recvfrom(sock, data, 4, 0, remote, n);

   Тестировал в одноранговой локалке. Обнаружил следующее
  1) Если пишу несуществующий  remote-ip, то программа "виснет" на строчке recvfrom, то есть как и положено, так как ничего не приходило
  2) Если пишу существующий remote-ip и порт и на том компьютере создаю сокет с такими свойствами - тоже все в порядке, если с remote comp послал данные - они читаются, не послал - программа ждет...
 3) Если пишу существующий remote-ip  - то
если строчка sendto отсутствует - тоже все нормально, а вот если я сначала туда чего-нибудь пошлю - то recvfrom начинает мне выдавать какие-то данные, причем значение, возвращаемое функцией - что-то порядка 4-8 мегабайт данных... И вот это-то не ясно...
Что мне приходит, и в таких количествах, если тот комп мне ничего не посылал? Причем remote-port не занят никаким приложением, при тестировании я перебрал порядка 50 портов  - везде такая ерунда...
  Объясните мне, или подскажите ,где почитать...


 
Verg ©   (2004-03-25 22:37) [1]

1. Порт в адресе сокета - это 16 битовое без знака (unsigned short), хронящееся в сетевом порядке байт, а мы пока имеем дело только с LITTLE_ENDIAN. Ты же заполняешь это поле в порядке байт хоста. Так что, давай-ка htons(<port>) не забывай. (Host TO Network Short)
2. Я не вижу вообще где ты анализируешь результат recvfrom


 
3APA3A ©   (2004-03-26 08:39) [2]

2. Анализ это что-то типа такого
     i:=recvfrom(sock, data, 4, 0, remote, n);
     ShowMessage(IntToStr(i));
  и  i равно 4-8 мегабайтам... что само по себе странно, ведь я дал запрос на чтение только 4 байт...

1. Сетевой порядок байт - это младший байт по старшему адресу? так?
   Что такое LITTLE_ENDIAN?
   Как я понял из SDK и вашего ответа - htons просто меняет порядок байтов в переменной порта?
   mov ax, port
   xcng ah, al
   mov netport, ax?


 
Verg ©   (2004-03-26 11:23) [3]


> 1. Сетевой порядок байт - это младший байт по старшему адресу?
> так?
>    Что такое LITTLE_ENDIAN?
>    Как я понял из SDK и вашего ответа - htons просто меняет
> порядок байтов в переменной порта?


Именно - remote.sin_port:= htons(60000);


> 2. Анализ это что-то типа такого
>      i:=recvfrom(sock, data, 4, 0, remote, n);
>      ShowMessage(IntToStr(i));
>   и  i равно 4-8 мегабайтам... что само по себе странно,
> ведь я дал запрос на чтение только 4 байт...


Да ну, не межет того быть. Приведи полный код (и без ошибок при копировании paste :) ).


 
3APA3A ©   (2004-03-29 04:18) [4]

Код вот такой

function WaitForData(Sock:Integer;TimeOut:Cardinal):Integer;
var FDS:TFDset;
   Tv:TTimeval;
   Ptv:PTimeVal;
begin
 FD_ZERO(FDS);
 FD_SET(Sock,FDS);
 Ptv:=nil;
 if TimeOut<>INFINITE then
 begin
   Tv.tv_sec:=TimeOut div 1000;
   Tv.tv_usec:=(TimeOut mod 1000) * 1000;
   Ptv:=@Tv;
 end;
 Result:=Select(0,@FDS,nil,nil,Ptv);
end;

procedure a;
begin
 local.sin_family := AF_INET;
 local.sin_port := htons(55000);
 local.sin_addr.S_addr := inet_addr("127.0.0.1");

 remote.sin_family := AF_INET;
 remote.sin_port := htons(55001);
 remote.sin_addr.S_addr := inet_addr("127.0.0.1");

 WSAStartup(MakeWord(1, 1), lWSA);
 s := socket(AF_INET, SOCK_DGRAM, 0);
 bind(s, local, sizeof(local));

 data := 123;

 sendto(s, data, 4, 0, remote, sizeof(local));
 
 n:=WaitForData(s, 1000);
 if n > 0 then ShowMessage("data")
 else
   if n = 0 then ShowMessage("timeout");

объясните пожалуйста, почему этот код выводит мне сообщение "data", ведь ничего не приходило? Если убрать строчку sendto - то все нормально...


 
Polevi ©   (2004-03-29 09:47) [5]

как не приходило ?
sendto(s, data, 4, 0, remote, sizeof(local)); - это что по твоему ?


 
Polevi ©   (2004-03-29 09:49) [6]

гм, сорри, порт другой


 
Polevi ©   (2004-03-29 09:50) [7]

аа, сокет один, создай для сенда другой сокет


 
Verg ©   (2004-03-29 10:16) [8]


> объясните пожалуйста, почему этот код выводит мне сообщение
> "data", ведь ничего не приходило?


Потому, что на сокете s что-то произошло, что требует чтения из него.
Я надеюсь (опять надо именно надеяться), что перемнная n - типа
integer

N := Recv(S,....);
if N= SOCKET_ERROR then
 ShowMessage(SysErrorMessage(WSAGetLastError));


 
Verg ©   (2004-03-29 10:19) [9]

А происходит, скорее всего вот что:

WSAECONNRESET The virtual circuit was reset by the remote side executing a hard or abortive close. The application should close the socket as it is no longer usable. On a UPD-datagram socket this error would indicate that a previous send operation resulted in an ICMP "Port Unreachable" message.

UPD - это мелкософтовская очепятка :))


 
3APA3A ©   (2004-03-30 11:24) [10]

"аа, сокет один, создай для сенда другой сокет" - блин, я не хочу создавать другой сокет... UDP сокеты работают в дуплексном режиме (или как там это называется) и поэтому мне просто хочется разобраться...

Ясно... то есть, мне приходит просто датаграмма что порт недоступен, то есть система вызывает что-то типа sendto(mysocket, Port_Unreachable)?
 А где прочитать про формат этих служебных датаграмм?
 Или просто recvfrom смотрит что это служебный пакет и выдает мне уже не его, а просто SOCKET_ERROR ?
 Хотелось бы получше разобраться со всем этим...


 
Verg ©   (2004-03-30 11:42) [11]


> Ясно... то есть, мне приходит просто датаграмма что порт
> недоступен, то есть система вызывает что-то типа sendto(mysocket,
> Port_Unreachable)?
>  А где прочитать про формат этих служебных датаграмм?
>  Или просто recvfrom смотрит что это служебный пакет и выдает
> мне уже не его, а просто SOCKET_ERROR ?
>  Хотелось бы получше разобраться со всем этим...


Эти служебные датаграммы - это ICMP (RFC 792).
При отправке UDP датаграммы, сетевое ядро принимающей машинки смотрит, что порт назначения у этой датаграммы никто не обслуживает (нет UDP сокета с таким локальным портом) и ядро отправляет источнику этой UDP датаграммы ICMP пакет - "Порт недоступен". Приняв это ICMP сообщение твое ядро переводит UDP сокет, отправивший ту датаграмму в состояние "готов к чтению, ошибка WSAECONNRESET". Вот и все. recv(from) из этого сокета вернет ошибку SOCKET_ERROR (-1), а WSAGetLastError сообщит, что WSAECONNRESET.

Надо помнить, что этого ICMP сообщения тот, принимающий хост может и не отправить (зависит от реализации) или это сообщение может не придти к тебе по причине файерволов, потерь при передаче и т.п.
Т.е. расчитывать на них не стоит, но и забывать про них тоже нелзя.

Учитесь (не забывайте) анализировать ошибки, возникающие при вызовах ф-ций работы с сокетами и соблюдать типы данных результатов этих ф-ций.


 
3APA3A ©   (2004-03-30 12:07) [12]

Все.. теперь все ясно.. кстати, что такое RFC 792?


 
Verg ©   (2004-03-30 12:18) [13]

http://delphimaster.net/view/6-1080561800/



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

Текущий архив: 2004.05.16;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.031 c
1-1082998352
Piter
2004-04-26 20:52
2004.05.16
Шрифты


14-1082726077
Igor_thief
2004-04-23 17:14
2004.05.16
Градиентная линия


3-1082570720
alle
2004-04-21 22:05
2004.05.16
Проблема в DataModule


3-1082555269
}|{yk
2004-04-21 17:47
2004.05.16
Master-detail в FIBPlus


3-1082354187
Top100
2004-04-19 09:56
2004.05.16
Оптимизация