Форум: "Сети";
Текущий архив: 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