Форум: "Сети";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];
ВнизНа отправляющий сокет приходит инфа, хотя приходить не должна... Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.039 c