Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > Проблема с ServerSocket и ClienSocket


Автор: darkida 26.1.2010, 13:45
Помогите разобраться. 
Перечитал весь форум. Некоторые пишут что разобрались со своей бедой, но не пишут как. В общем не нашел так и ответов на свой вопросы. 
Я хочу создать клиент серверную прогу. Но уже в самом начале повсюду одни обломы.
1. Неужто нельзя пользоваться средством  ServerSocket и ClientSocket путем интернета если нет постоянного IP адреса.
2. Почему моя программа принимает IP тот который мне выдает ipconfig в строке выполнения задач, а не тот который определяется в интернете.
3. Прога вообще не реагирует на задания клиента:
 а) потому что я тестю её на одном компе
 или 
 б) Ошибки в кодинге (хотя это мало вероятно, потому что пробовал элементарки, нифига не пашет)
но при этом как я понял прога распознает сервера потому что если указать другой адрес то начинает ругаться и выводить ошибки 10060, 10061, 10057, 10054. 

4. И я так понимаю еще могут проблемы с фаерволом возможно ли в дальнейшем научить программу обходить её или выключать программным путем.

Помогите пожалуйста. 

{Я отношусь пока что к числу чайников. И если можно то на понятном языке для чайника писать. )))) } 
Заранее благодарен. 

Автор: darkida 26.1.2010, 15:43
Мда тока что проверил через нет. Закинул другу и ввел ИП который выдает комп. А не нет. Работает также. То есть как я понял находит сервер, но опять нифига не делает. Почему находит, потому что при введений другого ИП адреса выдает ошибки. Значит как это не печально, но я труба слепой что не могу найти ошибку в кодинге. Но радует то что нет тех самых ошибок которых я писал выше. Все работает. И фаирвол и антивир ничего не делают. Это радует.
Помогите с кодингом где что ни так. Кодинг упростил на нуль чтоб получить хоть какой-то резудьтат от сервера. Ах да некоторые части взял с drkb. Там были примеры на эту тему, но также не пашут. 
СЕРВЕР
Код

unit server;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ScktComp, StdCtrls;

type
  TForm1 = class(TForm)
    ServerSocket1: TServerSocket;
    Button1: TButton;
    Memo1: TMemo;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure ServerSocket1Listen(Sender: TObject;
Socket: TCustomWinSocket);
    procedure ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
    procedure ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
    procedure ServerSocketlClientRead(Sender: TObject;
Socket: TCustomWinSocket);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  i:string;

implementation

{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines.Insert(0,'Server starting');
end;

procedure TForm1.ServerSocket1Listen(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo1.Lines.Insert(0,'Listening on port '+IntToStr(ServerSocket1.Port));
end;

procedure TForm1.ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo1.Lines.Insert(0,'Client connection accepted');
end;

procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Socket.SendStream(TFileStream.Create('c\1.txt', fmOpenRead or fmShareDenyWrite));
end;

procedure TForm1.ServerSocketlClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
s: String;
begin
s := Socket.ReceiveText;
if s='r'
 then
label1.Caption:=' privet';
end;

end.


КЛИЕНТ
Код

unit klient;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, ScktComp;

type
  TForm1 = class(TForm)
    Client: TClientSocket;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    IP: TEdit;
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
    procedure ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
    procedure ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    FStream: TFileStream;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  i: string;

implementation

{$R *.dfm}

procedure TForm1.ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
FStream := TFileStream.Create('с:\2.txt', fmCreate or fmShareDenyWrite);
end;

procedure TForm1.ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
if Assigned(FStream) then
begin
   FStream.Free;
   FStream := nil;
end;
end;

procedure TForm1.ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
iLen: Integer;
Bfr: Pointer;
begin
iLen := Socket.ReceiveLength;
GetMem(Bfr, iLen);
try
   Socket.ReceiveBuf(Bfr^, iLen);
   FStream.Write(Bfr^, iLen);
finally
   FreeMem(Bfr);
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
client.close;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
form1.close;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
//Client.active:=true;
Client.Address:=IP.text;
Client.Socket.SendText('r');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
FStream := nil;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(FStream) then
begin
   FStream.Free;
   FStream := nil;
end;                 
end;

end.


Как вы видите тут 3 варианта для проверки:
1.procedure TForm1.ServerSocket1Accept(Sender: TObject; Socket: TCustomWinSocket); который должен вывести список подключенных клиентов
2.procedure TForm1.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket); который должен отправить мне файл 
3. procedure TForm1.ServerSocketlClientRead(Sender: TObject; Socket: TCustomWinSocket); который должен изменить лабел
Ни один из этих вариантов не откликается. 
Помогите пожалуйста.

Автор: kami 26.1.2010, 15:58
Цитата(darkida @  26.1.2010,  13:45 Найти цитируемый пост)
1. Неужто нельзя пользоваться средством  ServerSocket и ClientSocket путем интернета если нет постоянного IP адреса.

Можно, но связано с большими заморочками. IP адрес не обязательно должен быть постоянным, главное - чтобы IP сервера был "виден" из интернета. Это возможно в следующих случаях:
1. "Белый" IP - то, что показывает ipconfig и то, что показывают всякие сервисы в интернете совпадает.
2. Если не совпадает - значит компьютер сидит за NAT, которая переадресовывает информацию внешний_IP<=>IP_компьютера_в локалке. В этом случае можно попросить провайдера дать Вам свой внешний IP. Они могут это сделать либо дав Вам пункт 1, либо сделав прямую переадресацию внешнийIP - внутренний. В этом случае клиент должен коннектиться на внешний IP сервера, а там уже посредством переадресации пакеты попадут "куда надо".
Проблема с динамическим IP, видимым из интернета одна - узнать, какой внешний IP сейчас, в данный момент, имеет сервер. Это чревато боком, посему чаще всего динамические IP просто не рассматривают.

Цитата(darkida @  26.1.2010,  13:45 Найти цитируемый пост)
 Почему моя программа принимает IP тот который мне выдает ipconfig в строке выполнения задач, а не тот который определяется в интернете.

см. пункт 2 предыдущего высказывания.

Цитата(darkida @  26.1.2010,  13:45 Найти цитируемый пост)
 Прога вообще не реагирует на задания клиента:

Трассировку никто не отменял. Сетевым TCP приложениям глубоко параллельно, работают они на одном компьютере или на разных - если коннект произошел, всё остальное - проблемы кода, что подтверждается этим:
Цитата(darkida @  26.1.2010,  13:45 Найти цитируемый пост)
 прога распознает сервера потому что если указать другой адрес то

то есть - коннект идет.

Цитата(darkida @  26.1.2010,  13:45 Найти цитируемый пост)
 И я так понимаю еще могут проблемы с фаерволом возможно ли в дальнейшем научить программу обходить её или выключать программным путем.

Виндовый - можно. А как быть с Outpost, Kaspersky, Kerio и всеми остальными? Здесь выход один - при установке программы сказать пользователю "для нормальной работы программы откройте пожалуйста такие и такие порты. Если не знаете как - обратитесь к сисадмину. Если его нет - выкиньте программу."

Добавлено через 8 минут и 35 секунд
Цитата(darkida @  26.1.2010,  15:43 Найти цитируемый пост)
 не могу найти ошибку в кодинге. 

Сервер вообще выводит что-нибудь типа "Listening ..." Client connection accepted и т.п. ?

Автор: kami 26.1.2010, 16:20
Тогда вопрос:
эти процедуры назначены компонентам TClient|TServerSocket? Или просто "висят" в published - секции?
Проверяется так:
выделив нужный компонент, в инспекторе объектов(F11) переходим на вкладку Events и смотрим там, есть ли что-нибудь напротив OnListening|OnAccept|OnConnect и т.п.?  (в принципе, вопрос из ряда параноидальных, но тем не менее).

Автор: darkida 26.1.2010, 16:31
Kami спасибо большое. Все четко и ясно, прям как я хотел, в точку. А то я не мог найти ответы на свой вопросы. 
Цитата

А как быть с Outpost, Kaspersky, Kerio и всеми остальными? Здесь выход один - при установке программы сказать пользователю "для нормальной работы программы откройте пожалуйста такие и такие порты.

Так порты же изначально мы сами задаем. Просто как я понимаю их антивири и фаерволы перехватывают и они не доходят до адресата. Или ты имеешь виду открыть доступ в этих приложениях на нужные порты?

Цитата

Сервер вообще выводит что-нибудь типа "Listening ..." Client connection accepted и т.п. ? 

И что с этим делать то? 

А да в кодинге ошибка есть, ну не ошибка просто забыл снять

procedure TForm1.Button4Click(Sender: TObject);
begin
//Client.active:=true;  ---- вот здесь
Client.Address:=IP.text;
Client.Socket.SendText('r');
end;

А и кстати если client.active:=true;  стоит выше  Client.Address:=IP.text; то выходит ошибка, а если ниже то все ОК. Хотя я думаю что правильнее было бы если была бы выше. Может здесь напортачил а?

Автор: kami 26.1.2010, 16:37
Цитата(darkida @  26.1.2010,  16:31 Найти цитируемый пост)
Так порты же изначально мы сами задаем. 

Ну да. Но если файрволлу не сказать "вот с этого порта, открытого в этой программе данные нужно пропускать", то он и не пропустит.
Цитата(darkida @  26.1.2010,  16:31 Найти цитируемый пост)
И что с этим делать то?

Проект без экзешника (только dpr, dfm, pas) - в зип и приаттачить сюда.
Пока скажу только, что 
Цитата(darkida @  26.1.2010,  16:31 Найти цитируемый пост)

procedure TForm1.Button4Click(Sender: TObject);
begin
//Client.active:=true;  ---- вот здесь
Client.Address:=IP.text;
Client.Socket.SendText('r');
end;

так - неправильно. Сперва назначают адрес/порт, потом активируют, клиент должен присоединиться, а уже потом можно отправлять через сокет данные.

Автор: darkida 26.1.2010, 16:49
Ну я дибил. Сам от себя в шоке. Извини Kami что отнял у тебя время.  Спасибо. Пздц тупанул, пойду высплюсь. Я ничего не проставил ни в Клиенте, ни в Сервере. А еще бесился на Delphi.  Мда проверил пашит собака. Правда пока проставлял еще нашел ошибки. 
Исправлю все и еще раз выложу может кому понадобится, хотя в DRKB и так все есть. Ну на всякий может я ни один такой.
Спасибо большое.

Автор: darkida 26.1.2010, 20:42
Вот так беда!!! 
Почти ведь все провайдеры выдают внутренние локальные IP адреса. 

Как тогда действуют трояны? У них что свой маршрутизаторы которые могут перекидываться из внешнего во внутренний? Но тогда провайдеры бы сразу отлавливали бы их. 

И самые защищенные IP адреса - это динамические что ли?
Хотя помниться когда сидел на обычном dial upe вирусов было не меньше. Среди которых присутствовали и трояны. 

Может все таки есть метод программным путем обойти. И вообще ServerSocket c ClientSocket'ом вызывают довольно много хлопот:
1. Просить всех пользователей чтоб бегали к админу, чтоб он настроил им их фаервол и антивириком.
2. Просить всех пользователей чтоб упрашивали провайдеров, чтоб они им сделали "Белый" IP. 
Это какая должна быть программа, чтоб люди на это согласились.  )))).
Может я опять поторопился и есть алтернатива Server и ClientSocket'у.
Потому что если даже есть вариант обойти эти 2 пункта программным путем то я даже не представляю на сколько он тяжелее написания самой проги.

Автор: darkida 26.1.2010, 21:15
http://forum.vingrad.ru/forum/topic-288166/kw-%D1%81%D0%B5%D1%82%D0%B8-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80-%D0%BB%D0%BE%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9.html
Здесь FOX пишет:
Цитата

Если приложение клиент-сервер, то НАТ исключительно транслирует адреса, остальное не его собачьего ума дела... Если прокси или ВПН, то может понадобится аутонтификация. 

Так вот она на практике ни черта не транслирует адреса. Прога сразу вылетать будет. Надо что то дополнительно прописывать.

Автор: kami 26.1.2010, 21:28
Цитата(darkida @  26.1.2010,  20:42 Найти цитируемый пост)
Почти ведь все провайдеры выдают внутренние локальные IP адреса. 

Да. Гораздо проще организовать свою локальную сеть, и иметь ограниченное количество "внешних" IP, выделяемых динамически, чем давать каждому пользователю один  из дефицитных адресов.
Цитата(darkida @  26.1.2010,  20:42 Найти цитируемый пост)
Как тогда действуют трояны? 

А что трояны? "Белый" IP должен быть у сервера. А клиент пусть сидит хоть за десятью маршрутизаторами. Ведь инициатор подключения - это клиент. И всякие маршрутизаторы знают, как "выпустить" его во всемирную паутину (обратное далеко не всегда верно). Трояны - это клиенты. Они знают IP сервера, на который нужно передать информацию с зараженного компьютера, устанавливают соединение... дальше, как я и говорил - проблемы кода, что и когда будет передано.
Цитата(darkida @  26.1.2010,  20:42 Найти цитируемый пост)
И самые защищенные IP адреса - это динамические что ли?

Нет. Самый защищенный адрес - это 127.0.0.1, при условии не-имения других IP. Все остальные - потенциальная уязвимость.

Цитата(darkida @  26.1.2010,  20:42 Найти цитируемый пост)
 И вообще ServerSocket c ClientSocket'ом вызывают довольно много хлопот:

Я открою тебе страшную тайну - на самом деле оба эти компонента - всего лишь обертка над виндовыми функциями работы с сетью. И все имеющиеся на настоящее время компоненты/классы для работы по TCP используют именно их (функции Windows) в той или иной манере. А TServer|ClientSocket - всего лишь минимальная надстройка, позволяющая более-менее удобно работать с соединением.

Цитата(darkida @  26.1.2010,  20:42 Найти цитируемый пост)
2. Просить всех пользователей чтоб упрашивали провайдеров, чтоб они им сделали "Белый" IP. 

Это нужно только для компьютера, на котором стоит серверная часть программы. Еще раз - клиент может сидеть хоть за десятью NAT, маршрутизаторами и т.п...

Автор: darkida 26.1.2010, 21:54
Мда похоже я опять ошибался. Потому что планировалось отправлять всем пользователям СЕРВЕР, а самому сидеть как КЛИЕНТ.  Ну так по крайней мере в моем кодинге. Хотя ведь по идее разницы нет. СЕРВЕР ведь обладает почти всеми теми же функциями что и КЛИЕНТ. За исключением выбора  IP адреса сервера. Но оно и мне надо. Мне легче будет я просто укажу свой IP и все.  Я почему то не задумывался над этим. Спасибо ещё раз. 
Вот ещё прочитал в нете. 
Возможно ли это одним из вариантов решения, а именно программным переходом из внешнего во внутренний адрес IP:
Цитата

DMZ - (Demilitarized Zone) - это дополнительная возможность Интернет- маршрутизаторов серии DI-XXX, предназначенная для предоставления доступа к внутренним (то есть находящимися за маршрутизатором и защищенных NAT-ом) серверам (таким, как почтовый, WWW, FTP) пользователям из Интернет. Но, в отличие от "Virtual Servers", когда отображается только один порт, в данном случае запрос извне на любой порт внешнего (WAN) интерфейса отображается на такой же порт компьютера, указанного в настройках DMZ.
То есть, все открытые порты на этом компьютере доступны снаружи.
Это может создать угрозу безопасности для данного компьютера, поэтому на данном компьютере возможно будет необходимо установить программный межсетевой экран для защиты. Рекомендуется использовать данный метод только тогда, когда другими способами не удается обеспечить правильную работу сервисов на этом компьютере.
Например, для работы некоторых игровых серверов требуется обеспечить отображение большого количества портов или адреса портов назначаются таким сервером динамически в широком диапазоне.

Автор: kami 26.1.2010, 22:05
Цитата(darkida @  26.1.2010,  21:54 Найти цитируемый пост)
 Потому что планировалось отправлять всем пользователям СЕРВЕР, а самому сидеть как КЛИЕНТ.

Я так понимаю, что идет разработка программы удаленного доступа?
Цитата(darkida @  26.1.2010,  21:54 Найти цитируемый пост)
 планировалось отправлять всем пользователям СЕРВЕР, а самому сидеть как КЛИЕНТ.

Если это будет происходить в пределах одного провайдера - то никакие "белые", "внешние" и т.п. IP не нужны, достаточно пользоваться локальными.

Цитата(darkida @  26.1.2010,  21:54 Найти цитируемый пост)
 Хотя ведь по идее разницы нет. СЕРВЕР ведь обладает почти всеми теми же функциями что и КЛИЕНТ. 

После установки соединения разницы нет абсолютно, за исключением одного - TServerSocket может иметь кучу соединений, TClientSocket - только одно.
Цитата(darkida @  26.1.2010,  21:54 Найти цитируемый пост)
Возможно ли это одним из вариантов решения, а именно программным переходом из внешнего во внутренний адрес IP:

Это касается конкретных маршрутизаторов, и если провайдер не использует DMZ, никто не заставит его это сделать. smile

Добавлено через 4 минуты и 19 секунд
Цитата(darkida @  26.1.2010,  21:54 Найти цитируемый пост)
Потому что планировалось отправлять всем пользователям СЕРВЕР, а самому сидеть как КЛИЕНТ. 

Ну и внеси изменения, которые не должны повлиять на логику программы:
пусть у тебя "белый" IP, и TServerSocket.
У пользователей - "серые" IP и TClientSocket.
Пусть пользовательские программы через определенные промежутки времени пытаются подключиться к твоему компьютеру. Подключился - пошел обмен, регулируемый тобой, как задавателем логики программы.

Автор: darkida 26.1.2010, 22:32
Цитата

Я так понимаю, что идет разработка программы удаленного доступа?

Тока планируется, тем более с моими то знаниями в программирование, это ой как затянется чувствую. )) 
Цитата

Если это будет происходить в пределах одного провайдера - то никакие "белые", "внешние" и т.п. IP не нужны, достаточно пользоваться локальными.

Мда такое только не получится. Я в Китае. )) И чувствую на долго здесь. А и кстати у меня тоже здесь локалка, но надеюсь договорится со здешними админами, это проще чем просить всех. ))
Цитата

После установки соединения разницы нет абсолютно, за исключением одного - TServerSocket может иметь кучу соединений, TClientSocket - только одно.

Мда это нормально даже. Зато контролить легко наверно будет. 
Цитата

Это касается конкретных маршрутизаторов, и если провайдер не использует DMZ, никто не заставит его это сделать. 
е 
Печально, а я то думал.......... Что это станет пустяшным делом используя её.

Ты мне страшно помог. Кроме тебя здесь никто и не пишет то. Только вот тебе не повезло то что я обычный студент, без наворотов и нет возможности отблагодарить деньгами. Но если ты играешь в доту или в покер, то виртуальных бабок жалко не будет. 

Автор: kami 26.1.2010, 22:48
Цитата(darkida @  26.1.2010,  22:32 Найти цитируемый пост)
Тока планируется, тем более с моими то знаниями в программирование, это ой как затянется чувствую. )) 

Нормально, программа сетевого администрирования была моим первым серьезным проектом на Delphi, и развивал ее я с 2004 по 2008 smile.
Я тоже сделал "через одно место" - в подавляющем большинстве программ этого направления управляемая часть - это сервер, а админ пользуется клиентом. Мне это изначально показалось очень проблематичным, я пошел тем путем, который озвучил тебе. Так как программа позиционировалась для работы в локалке, то это было более чем оправдано для облегчения мне задачи.

Добавлено через 57 секунд
Удачи!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)