Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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.56 MB
Время: 0.027 c
1-1131899674
Toxa_ua
2005-11-13 19:34
2005.12.18
Как в компонент ListBox вставить в фон картинку jpeg?


2-1132786540
Дева
2005-11-24 01:55
2005.12.18
CommaText


14-1132758402
lookin
2005-11-23 18:06
2005.12.18
Локаут и повседневность. USA vs Россия.


2-1133705443
Vadim14
2005-12-04 17:10
2005.12.18
vc++ dll


9-1122218078
Большой Брат
2005-07-24 19:14
2005.12.18
Антилязинг