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

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.014 c
1-1132813677
Tapok
2005-11-24 09:27
2005.12.18
Считать большой файл частями


2-1133717060
SergP
2005-12-04 20:24
2005.12.18
Tmemo и TListView на TNotebook = Страшные Глюки


2-1133309980
Toxa_ua
2005-11-30 03:19
2005.12.18
OpenDialog -->†


4-1129626881
ShiFT
2005-10-18 13:14
2005.12.18
WinHotKeyCtrl


6-1125558278
integery
2005-09-01 11:04
2005.12.18
што значит range check error





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