Текущий архив: 2005.12.18;
Скачать: CL | DM;
ВнизClient/ServerSockets. Как найти все сокеты, активные в сети? Найти похожие ветки
← →
Курдль (2005-07-28 11:43) [0]Привет, коллеги!
Нужно простое решение для поиска серверов внутри локальной сети. Допустим, что у них открыты сокеты на прослушивание по одному и тому же порту.
На низшем уровне, вроде, все понятно как делалось. Ставились прослушиватели на определенный порт, а с клиента отправлялся широковещательный запрос. Оставалось поймать и расшифровать
все ответы. А как это сделать средствами Delphi?
Наверняка уже обсуждалось, так что можете просто отправить на нужную ветку.
← →
kblc © (2005-07-28 12:05) [1]Поставьте мне тоже прослушиватель ;)
А вообще, ковыряй либо WinAPI socket либо TServerSocket & TClientSocket
← →
Курдль (2005-07-28 12:11) [2]//Поставьте мне тоже прослушиватель ;)
Да легко!VCL Reference
TServerWinSocket.Listen
Но меня интересуют действия клиента!
//А вообще, ковыряй либо WinAPI socket либо TServerSocket & TClientSocket
А вообще не бжи - перед тем как залезть на форум со своим дурацким вопросом, я прочитал все, что нашел в 2-х книгах про Делфи по 800-1000 страниц каждая.
← →
Digitman © (2005-07-28 12:17) [3]
> Ставились прослушиватели на определенный порт, а с клиента
> отправлялся широковещательный запрос
нестыковочка, мягко говоря, получается ..
listen() предполагает TCP-протокол, а "широковещательный запрос" - UDP-протокол
и как ты при этом умудряешься "ловить" UDP-сообщения TCP-гнездом - только одному тебе и богу известно)
← →
kblc © (2005-07-28 12:21) [4]Удалено модератором
← →
Курдль (2005-07-28 12:23) [5]"Listen" я привел навскидочку в ответ на высказывание предыдущего автора.
Извините, - был слегка раздосадован ответом не по существу.
Так как Вы предлагаете решить мою несложную проблему?
← →
Digitman © (2005-07-28 12:32) [6]
> Курдль (28.07.05 12:23) [5]
> "Listen" я привел навскидочку в ответ на высказывание предыдущего
> автора.
нет уж ты уж определись для начала, какое гнездо у тебя на серв.стороне - UDP или TCP ..
для UDP-гнезд понятие "прослушивание" (listen) вообще не применимо
← →
kblc © (2005-07-28 12:36) [7]Курдль, Сформулируй правильно вопрос и будет тебе счастье!
← →
kblc © (2005-07-28 12:39) [8]
procedure Tfm_SQL_Update.GetServersList(Storage: TStrings);
var
hSocket: TSOCKET;
WSAData: TWSAData;
Buf: array[0..65535] of byte;
i,iBeg,tRes,tLenSA,tLenBufRecv,tFlagStep: integer;
tLenBufIOCTL: u_long;
S,S2,S3: AnsiString;
saSQLSend,saSQLRecv: sockaddr_in;
Data: byte;
const
fBroadcast: boolean = TRUE;
begin
Data:=$02;
Storage.Clear;
WSAStartup(MakeWord(2,2), WSAData);
hSocket:=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (hSocket = INVALID_SOCKET) then exit;
tRes:=setsockopt(hSocket,SOL_SOCKET,SO_BROADCAST,@fBroadcast,sizeof(BOOL));
if (tRes = SOCKET_ERROR) then
begin
closesocket(hSocket);
exit;
end;
saSQLSend.sin_family :=AF_INET;
saSQLSend.sin_port:=htons(1434);
saSQLSend.sin_addr.s_addr:=htonl(INADDR_BROADCAST);
tRes:=sendto(hSocket,Data,1,0,saSQLSend,sizeof(SOCKADDR_IN));
if (tRes=SOCKET_ERROR) then
begin
closesocket(hSocket);
exit;
end;
Sleep(100);
tRes:=ioctlsocket(hSocket,FIONREAD,tLenBufIOCTL);
if (tRes=SOCKET_ERROR) then
begin
closesocket(hSocket);
exit;
end;
if (tLenBufIOCTL>0) then
begin
tFlagStep:=0;
tLenSA:=sizeof(SOCKADDR_IN);
saSQLRecv:=saSQLSend;
while tLenBufIOCTL>0 do
begin
tLenBufRecv:=recvfrom(hSocket,Buf,65535,0,saSQLRecv,tLenSA);
tLenBufIOCTL:=tLenBufIOCTL-tLenBufRecv;
if(tLenBufRecv=SOCKET_ERROR) then
begin
closesocket(hSocket);
exit;
end;
iBeg:=1;
S2:="";
for i:=3 to tLenBufRecv-3 do S2:=S2+Chr(Buf[i]);
tLenBufRecv:=tLenBufRecv-3;
for i:=1 to tLenBufRecv-3 do
begin
if(S2[i]=";") then
begin
S:=Copy(S2,iBeg,i-iBeg);
if (tFlagStep=1) then S3:=S;
if (tFlagStep=2) then
begin
if(S<>"MSSQLSERVER") then S3:=S3+("\\"+S);
Storage.Add(S3);
S3:="";
end;
tFlagStep:=0;
if(S="ServerName") then tFlagStep:=1;
if(S="InstanceName") then tFlagStep:=2;
iBeg:=i+1;
end;
end;
end;
end;
closesocket(hSocket);
WSACleanup;
Storage.Add("LOCALHOST");
end;
Вот тебе пример поиска SQL сервером, которые открывают 1434 UDP порт.
Разберёшься?
← →
Курдль (2005-07-28 12:45) [9]Спасибо. Пошел разбираться.
Извиняюсь за крайнее косноязычие, но Вы же мой вопрос в конце концов поняли?! :)
← →
Курдль (2005-07-28 12:52) [10]Спасибо, kblc ©!
Все отработало, как надо.
Ща только почищу все, что касается MS SQL и вперед!
← →
Digitman © (2005-07-28 12:54) [11]
> Вы же мой вопрос в конце концов поняли?
я ? нет) .. я так и не понял, кто и что там у тебя "слушает" на серв.стороне - ты ведь "навскидочку" упомянул Listen(), всуе тэкскэть ..
у TCP-сервера д.б. TCP-клиент
а TCP-клиент не умеет делать broadcast, его умеет делать UDP-"клиент"
и каким макаром ты умудряешься "снюхать" UDP-"клиента" с TCP-сервером - просто ума не приложу)
← →
Курдль (2005-07-28 13:09) [12]> Digitman ©
Мля! Какая ж ты зануда!!!
Мне было бы достаточно получить по UDP сетевые адреса активных в данный момент элементов распределенной системы. Как оно все у меня будет работать тебе надо?
Лучше последуй примеру доброго и щедрого, хоть и ироничного kblc ©
и дай пример, как ответить на broadcast сообщение!
← →
Polevi © (2005-07-28 13:18) [13]используй ф-ию send
← →
Digitman © (2005-07-28 13:39) [14]
> Курдль (28.07.05 13:09) [12]
"мля"кай с пацанами в подворотне.
а здесь будь любезен сформулировать вопрос как положено - кратко, внятно, точно ..
> Ставились прослушиватели на определенный порт
вот как тебя понять ? ЧТО за "прослушиватели" такие ?
UDP-сервер как таковой не существует - любое UDP-гнездо способно выполнять ф-ции некоего рода "клиента" или "сервера", в отличии от TCP-гнезда ..
UDP-гнездо ничего не "прослушивает" - оно просто принимает дейтаграммы с любого адреса в сети, интерфейс которой был указан при его bind(), в т.ч. и дейтаграммы, разосланные бродкастом любым другим (передающим) UDP-гнездом
Listen() же ("прослушивание вх.запросов на соединение") вообще не применим к UDP-гнездам, потому как этот механизм используется лишь для протоколов, подразумевающих установку логического p2p-соединения перед тем как будет начат собстенно прикладной инф.обмен между двумя гнездами
Так что твое "прослушивание" как способность ожидать и принимать UDP-гнездом адресованые ему (непосредственно или бродкастом) дейтаграммы и "прослушивание" как способность ожидать TCP-гнездом входящие клиентские запросы на соединение и акцептировать их (возможно - условно) - это две разные разницы !
> дай пример
что за "дай" ?! ты в богадельню явился ?
и что значит "пример" ? ты даже не сподобился уточнить, гнезда как WinsockAPI-объекты или гнезда как Делфи-объекты тебя интересует, а пример при этом (непонятно для каких гнезд) тебе вынь да положь ?
> как ответить
на WinsockAPI так и ответь - sendto() ..
в recvfrom() предпосл.параметром ты получаешь адрес отправителя принятой дейтаграммы, его же и используй в кач-ве адреса получателя ответной дейтаграммы
← →
Курдль (2005-07-28 13:53) [15]Уважаемый Digitman ©!
Надеюсь, что с этого момента мы будем общаться только "на Вы".
На этот форум приходят за помощью. Именно в надежде, что ее "Дадут", а не "Продадут" или боросят, как кость.
В былые времена я охотно делился своими знаниями, касающимися работы с данными. А вот с работой в сетях у меня как-то не задалось.
Спасибо за подробные выкладки моей некомпетентности.
А особенно - за дельный совет, содержащийся (к сожаленнию только) в последней строчке.
← →
kblc © (2005-07-28 13:59) [16]2Polevi:
send используеться для TCP клиента.
2All: нужно использовать sendto, а на сервере нужно использовать recvfrom
← →
Polevi © (2005-07-28 14:20) [17]>kblc © (28.07.05 13:59) [16]
ты прав, но не факт что у него UDP сервер
← →
Курдль (2005-07-28 14:28) [18]//ты прав, но не факт что у него UDP сервер
У меня пока нет никакого сервера.
И я не ограничен никакими строгими условиями сохранности / безопасности данных. Если вы, как высококвалифицированные специалисты, посоветуете мне UDP - я сработаю и с ним.
Если у кого-то есть кусочек кода, который мог бы стать "ответной частью" процедуры, любезно предоставленной kblc ©, я был бы просто счастлив!
← →
Polevi © (2005-07-28 14:37) [19]unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Winsock2,
StdCtrls, Scktcomp, ExtCtrls;
const
UDPPort=222;
type
TT=class(TThread)
private
FSocket:TSocket;
FAddr: TSockAddrIn;
FWnd:THandle;
protected
procedure Execute;override;
public
constructor Create(AWnd:THandle);reintroduce;
end;
type
TForm1 = class(TForm)
Timer1: TTimer;
Memo1: TMemo;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure OnMsg(var Msg:TMessage);message WM_USER+1;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
var
WSAData:TWSAData;
begin
if WSAStartup($0202,WSAData)<>0 then
raise Exception.Create("Cannot load winsock!");
TT.Create(Handle);
end;
procedure TForm1.OnMsg(var Msg: TMessage);
begin
Memo1.Lines.Add(PChar(Msg.wParam));
end;
constructor TT.Create(AWnd: THandle);
begin
FWnd:=AWnd;
inherited Create(false);
end;
procedure TT.Execute;
var
Buffer:Pointer;
Len:integer;
evt:THandle;
bytesRecvd:integer;
const
bufLen=512;
begin
GetMem(Buffer,bufLen);
try
try
FSocket := socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
FAddr.sin_family := AF_INET;
FAddr.sin_addr.s_addr := INADDR_ANY;
FAddr.sin_port := htons(UDPPort);
if bind(FSocket, @FAddr, SizeOf(FAddr))=SOCKET_ERROR then
RaiseLastWin32Error;
evt:=CreateEvent(nil,false,false,nil);
WSAEventSelect(FSocket,evt,FD_READ);
while not Terminated do
begin
WSAWaitForMultipleEvents(1,@evt,false,INFINITE,false);
Len:=sizeof(FAddr);
bytesRecvd:=recvfrom(FSocket,Buffer^,bufLen,0,FAddr,Len);
if bytesRecvd=SOCKET_ERROR then
RaiseLastWin32Error;
SendMessage(FWnd,WM_USER+1,Integer(Buffer),bytesRecvd);
end;
CloseHandle(evt);
closesocket(FSocket);
except
end;
finally
FreeMem(Buffer);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ASocket:TSocket;
Addr: TSockAddrIn;
Len:integer;
BroadCast:boolean;
begin
BroadCast:=false;
ASocket := socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
setsockopt (ASocket,SOL_SOCKET,SO_BROADCAST,PChar(@BroadCast),sizeof(boolean));
Addr.sin_family := AF_INET;
Addr.sin_addr.s_addr := inet_addr(PChar("192.168.1.22"));
Addr.sin_port := htons(UDPPort);
Len:=sizeof(Addr);
if sendto(ASocket,PChar("hello world")^,12,0,Addr,Len)=SOCKET_ERROR then
RaiseLastWin32Error;
closesocket(ASocket);
end;
end.
← →
Polevi © (2005-07-28 14:42) [20]setsockopt (ASocket,SOL_SOCKET,SO_BROADCAST,PChar(@BroadCast),sizeof(boolean));
убери, он тебе не нужен
← →
Курдль (2005-07-28 14:49) [21]Ага, спасибо. Что-то делфя сама не нашла unit Winsock2.
Сейчас попробую вручную.
← →
Alexey_FireMan (2005-07-28 14:57) [22]Что конкретно ты собираешся передавать и проверять?
Если ты хочешь проверить включены ли машины у тебя в локалке то проще всего использовать UDP. На (Клиентских машинах) просто создаеш сокет скажем порт $3218, а с (серверной) отсылаеш широковещательный запрос, в свою же очередь клиент получив запрос и адрес (серверной) выполняет (подлючается по TCP или отсылает пакет с подтверждением о включенности по UDP) действия.
Такой способ не сильно грузит сетку, т.е. сервер не отослал запрос клиент сидит тихо!
← →
Digitman © (2005-07-28 15:28) [23]
> Курдль (28.07.05 13:53) [15]
> Надеюсь, что с этого момента мы будем общаться только "на
> Вы".
без вопросов.
на "Вы" - значит на "Вы"... за фамильярность-панибратство готов принести персональные извинения, коль они того стоят в дан.ситуации
скажу лишь что мне так привычней.
> На этот форум приходят за помощью
Да.
> Именно в надежде, что ее "Дадут", а не "Продадут" или боросят,
> как кость
Да. Помощь не м.б. ассоциирована с "продать".
"Бросить как кость" - совершенно неуместно в дан.случае, ибо вопрос, повторяю, был задан КРАЙНЕ туманно и некорректно. И что было "брошенной костью" в дан.случае - весьма и весьма неоднозначтно.... "Кость" за "кость" ..
> с работой в сетях у меня как-то не задалось
я тоже с этого начинал - ничего страшного.
когда-то меня на этом форуме тоже ткнули носом - и я пошел читать док-цию и решил ту (ти все последующие) задачи самостоятельно.
> за дельный совет, содержащийся .. в последней
> строчке
преодоление некомпетентности д.б. быть начато не с "дай", а с поиска в Сети инф-ции на тему "сетевые протоколы информационного обмена"
← →
Digitman © (2005-07-28 15:30) [24]
> скажу лишь что мне так привычней
.. особенно в случаях, когда собеседник (оппонент) не зарегистрирован в Форуме как постоянный участник
← →
Курдль © (2005-09-11 22:42) [25]Спасибо всем за дельные советы, особенно Digitman ©, который заставил меня разобраться в существе вопроса, хоть на это ушло больше времени, чем планировалось. Правда по ходу "дознания" удалось выяснить неоспоримые преимущества "вижуал кролика" перед делфями и полностью переписать прогу на нем. Многообразие предопределенных классов-наследников Socket поразило мое воспаленное воображение. UDPClient, TCPListener и мн.др. да все с асинхронными методами! Прэлестно! А уж что говорить про ".NET Remoting"... Делфям такое и не снилось :(
← →
Fay © (2005-09-12 00:14) [26]2 Курдль © (11.09.05 22:42) [25]
> особенно Digitman ©, который заставил меня разобраться
> в существе вопроса
Преподобный Digitman обычно именно этого и добивается. IMHO, это лучшая подмога.
>> Делфям такое и не снилось :(
У них ("Делфей") хватает наяву.
Это как "Биться, так биться. Но зачем в #опу кричать?"...
← →
Eraser © (2005-09-12 13:43) [27]Курдль © (11.09.05 22:42) [25]
Делфям такое и не снилось :(
А как же D8/2005 ? )
UDPClient, TCPListener и мн.др. да все с асинхронными методами!
Сомнительное приемущество.
Страницы: 1 вся ветка
Текущий архив: 2005.12.18;
Скачать: CL | DM;
Память: 0.54 MB
Время: 0.013 c