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

Вниз

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

 
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;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.023 c
4-94239
SH
2003-12-22 12:59
2004.02.29
ActionManager - вкл./выкл кнопок панелей


1-93896
heady
2004-02-15 21:45
2004.02.29
как сделать кнопку


9-93745
wild
2003-08-15 04:35
2004.02.29
Математика в азартных играх.


1-93878
donkey
2004-02-16 12:15
2004.02.29
Поиск по файлу


1-93897
VID
2004-02-11 14:55
2004.02.29
Как выделить некий текст в TEmbeddedWB ?