![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
На отправляющий сокет приходит инфа, хотя приходить не должна... [D7, WinXP]
3APA3A © (2004-03-25 22:09:00)Объясните мне, пожалуйста, следующее
создаю сокет
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-30 12:18:00) [1]http://www.delphimaster.ru/cgi-bin/forum.pl?id=1080561800&n=4
3APA3A (2004-03-30 12:07:00) [2]Все.. теперь все ясно.. кстати, что такое RFC 792?
Verg (2004-03-30 11:42:00) [3]
> Ясно... то есть, мне приходит просто датаграмма что порт
> недоступен, то есть система вызывает что-то типа 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 11:24:00) [4]"аа, сокет один, создай для сенда другой сокет" - блин, я не хочу создавать другой сокет... UDP сокеты работают в дуплексном режиме (или как там это называется) и поэтому мне просто хочется разобраться...
Ясно... то есть, мне приходит просто датаграмма что порт недоступен, то есть система вызывает что-то типа sendto(mysocket, Port_Unreachable)?
А где прочитать про формат этих служебных датаграмм?
Или просто recvfrom смотрит что это служебный пакет и выдает мне уже не его, а просто SOCKET_ERROR ?
Хотелось бы получше разобраться со всем этим...
Verg (2004-03-29 10:19:00) [5]А происходит, скорее всего вот что:
WSAECONNRESETThe 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 - это мелкософтовская очепятка :))
Verg (2004-03-29 10:16:00) [6]
> объясните пожалуйста, почему этот код выводит мне сообщение
> "data", ведь ничего не приходило?
Потому, что на сокете s что-то произошло, что требует чтения из него.
Я надеюсь (опять надо именно надеяться), что перемнная n - типа
integer
N := Recv(S,....);
if N= SOCKET_ERROR then
ShowMessage(SysErrorMessage(WSAGetLastError));
Polevi (2004-03-29 09:50:00) [7]аа, сокет один, создай для сенда другой сокет
Polevi (2004-03-29 09:49:00) [8]гм, сорри, порт другой
Polevi (2004-03-29 09:47:00) [9]как не приходило ?
sendto(s, data, 4, 0, remote, sizeof(local)); - это что по твоему ?
3APA3A (2004-03-29 04:18:00) [10]Код вот такой
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 - то все нормально...
Verg (2004-03-26 11:23:00) [11]
> 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-26 08:39:00) [12]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-25 22:37:00) [13]1. Порт в адресе сокета - это 16 битовое без знака (unsigned short), хронящееся в сетевом порядке байт, а мы пока имеем дело только с LITTLE_ENDIAN. Ты же заполняешь это поле в порядке байт хоста. Так что, давай-ка htons(<port>) не забывай. ( Host TO Network Short)
2. Я не вижу вообще где ты анализируешь результат recvfrom