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

Вниз

Проблема с сокетами   Найти похожие ветки 

 
denkop   (2003-12-16 01:47) [0]

Делаю так:

function LookupName(const Name: string): TInAddr; {это я выдрал из VCL}
var
HostEnt: PHostEnt;
InAddr: TInAddr;
begin
HostEnt := gethostbyname(PChar(Name));
ShowMessage("1=");
FillChar(InAddr, SizeOf(InAddr), 0);
if HostEnt <> nil then
begin
with InAddr, HostEnt^ do
begin
S_un_b.s_b1 := h_addr^[0];
S_un_b.s_b2 := h_addr^[1];
S_un_b.s_b3 := h_addr^[2];
S_un_b.s_b4 := h_addr^[3];
end;
end;
Result := InAddr;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
nSMTPServerSocket := socket(PF_INET, SOCK_STREAM, 0);
ShowMessage(IntToStr(nSMTPServerSocket));{здесь нормально}
smtp_address.sin_family := AF_INET;
smtp_address.sin_addr:=LookupName("smtp.aaanet.ru");
smtp_address.sin_port := 25;
nConnect := connect(nSMTPServerSocket, smtp_address,sizeof(smtp_address));
ShowMessage(IntToStr(nConnect));{здесь -1}

for i:=1 to 7 do
begin
recv(nSMTPServerSocket, sBuf, sizeof(string), 0);
Memo1.Lines.Add(sBuf);
send(nSMTPServerSocket,MailMessage[iMsg], Length(MailMessage[iMsg]),0);
end;
ShowMessage("Complete");
end;

Мне кажется баг таится где-то в формировании sin_addr. Других вариантов не нашёл как по хосту получить ip.


 
Digitman   (2003-12-16 08:22) [1]

плохо ты "выдрал")

где вызов WSAStartup() ??

ты сам мог бы понять свою ошибку, если бы взял за хорошую привычку анализировать причину отказа winsock-функций вызовом WSAGetLastError()


 
denkop   (2003-12-16 19:04) [2]

Прошу не ругаться на меня, т.к. напрямую с winsock.pas ничего ранее не использовал.
Я исправился, вот код:
var
D:WSAData;
S:TSocket;
A:TSockAddr;
IPName:string;

begin
if HostToIP("smtp.aaanet.ru",IPName) then
WriteLn("IP=",IPName) else WriteLn("Error define IP");
{IP опред нормально}
if WSAStartup($101,D)<>0 then
begin
writeln("error WSAStartUp");
exit;
end;
A.sin_family:=AF_INET;
A.sin_addr.S_addr:=inet_addr(pchar(IPName));
A.sin_port := 25;
S:=socket(AF_INET,SOCK_STREAM,0);
if S=INVALID_SOCKET then writeln("error socket init")
else WriteLn("socket handle=",S);{Здесь тоже всё в норме}
if connect(S,A,sizeof(A))<>0 then
WriteLn("Cannot connect to socket, error: ",
WSAGetLastError); {А вот здесь всё плохо}
WSACleanup;
WriteLn("Complete");
ReadLn;
end.

После коннекта получаю ошибку 10061-WSAECONNREFUSED. Через telnet всё работает, т.е. сервер функционирует нормально.


 
Digitman   (2003-12-17 08:23) [3]

после успешного вызова socket(), но ПЕРЕД вызовом connect() ты обязан вызвать bind(), чтобы занять любой свободный порт


 
Digitman   (2003-12-17 08:28) [4]

это тебе в помощь

http://book.itep.ru/7/sock_71.htm

там ты найдешь графически представленную циклограмму, наглядно поясняющую механизм установления вирт.петли соединения при использовании TCP-протокола, а так же соотв.послед-ть Winsock-вызовов


 
Verg   (2003-12-17 09:50) [5]


> A.sin_port := htons( 25 );


 
Verg   (2003-12-17 10:03) [6]


> Digitman © (17.12.03 08:23) [3]
> после успешного вызова socket(), но ПЕРЕД вызовом connect()
> ты обязан вызвать bind(), чтобы занять любой свободный порт


Клиенту нет необходимости вызывать bind до вызова connect: при необходимости ядро выберет и динамически назначаемый порт, и IP-адрес отправителя.
Ядро выбирает IP-адрес отправителя в момент подключения клиента к сокету, основываясь на используемом исходящем интерфейсе, который, в свою очередь, зависит от маршрута, требуемого для обращения к серверу.


 
Digitman   (2003-12-17 10:13) [7]


> Verg


ты прав.
явный bind() нужен лишь серверной стороне


 
denkop   (2003-12-17 20:36) [8]


> Digitman

Дельная дока!
У меня не хватало htons( 25 );
Соединение получилось, но вот с приёмом передачей туго.
Вот получившийся код:

program Project1;

{$APPTYPE CONSOLE}

uses
SysUtils,
WinSock,
GFiles;

{$R *.res}

var
D:WSAData;
S:TSocket;
A:TSockAddr;
Buf,Cmd,IPName:string;
f:textfile;

begin
Assign(f,"debug.log");
try
Rewrite(f);
if HostToIP("smtp.aaanet.ru",IPName) then
WriteLn(f,"IP=",IPName) else WriteLn(f,"Error define IP");
if WSAStartup($101,D)<>0 then
begin
writeln(f,"error WSAStartUp");
exit;
end;
A.sin_family:=AF_INET;
A.sin_addr.S_addr:=inet_addr(pchar(IPName));
A.sin_port :=htons(25);
S:=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
if S=INVALID_SOCKET then writeln(f,"error socket init")
else WriteLn(f,"socket handle=",S);
if connect(S,A,sizeof(A))<>0 then
WriteLn(f,"Cannot connect to socket, error: ",WSAGetLastError)
else WriteLn(f,"Connected");
Cmd:="HELO smtp.aaanet.ru"+#10#13;
Send(S,Cmd,SizeOf(Cmd),0);
WriteLn(Cmd);
Recv(S,buf,255,0);
WriteLn(f,buf);
WriteLn(f,"Complete");
finally
WSACleanup;
Close(f);
end;
ReadLn;
end.

После Recv программа молча вылетает безо всяких предупреждений.


 
Digitman   (2003-12-18 08:27) [9]


> У меня не хватало htons( 25 );


надеюсь, тебе понятно, что делает эта ф-ция и почему


> После Recv программа молча вылетает безо всяких предупреждений


она (программа) и передает у тебя далеко не то что ты ожидаешь

//передача
BytesSent := Send(S,Cmd[0],Length(Cmd),0);

//прием
SetLength(buf, 255);
BytesReceived := Recv(S,buf[0], Length(buf),0);

p.s.
рановато ты взялся за API, потому как знания ObjectPascal у тебя оставляют желать лучшего


 
denkop   (2003-12-21 11:41) [10]

SetLength(buf, 255); - прощёлкал.
А почему Cmd[0] а не просто Cmd?


 
Digitman   (2003-12-21 13:54) [11]

и даже не Cmd[0], а Cmd[1] - это уже я ошибся

потому что Cmd[1] вернет ссылку на 1-й символ подготовленного строкового буфера (т.е. начало собственно буфера) , в то время как Cmd вернет ссылку не на начало буфера, а не адрес управляющей структуры, относящейся к переменной String (String = AnsiString - тип динамический, а не статический) ...

адрес начала дин.структуры и адрес начала буфера, на который ссылается некое поле этой дин.структуры - не одно и тоже


 
denkop   (2003-12-23 22:49) [12]

Мда, верно... Спасибо за помощь.



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

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

Наверх




Память: 0.47 MB
Время: 0.008 c
1-93960
OlimPer
2004-02-16 22:03
2004.02.29
ShellListView


1-93931
Артем К.
2004-02-15 06:28
2004.02.29
как узнать имя формы, на которую помещен компонент


11-93821
=Sniper=
2003-06-14 17:13
2004.02.29
В VCL работает правильно, а в KOL неправильно


1-93904
Rude
2004-02-15 22:03
2004.02.29
Как посчитать CRC какого то файла в Windows


8-94034
fiction
2003-10-28 22:34
2004.02.29
Использование Directsound





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский