Content


I-10: Ru.Delphi.Internet FAQ

I-20: Copyrights:

 Текущим  ведущим  FAQ  является  Den  Krep  (c)
 За  основу  взят  FAQ  RU.DELPHI.INTERNET  (c)  Vlad  Kiselev,  2001-2002
 частично  (c)  Alexey  Mahotkin,  1997..2000
 (c)  авторы  ответов  на  вопросы:
 
 Vlad  Kiselev,  2:5030/1095.6
 Andrei  Pangin,  pan@sbor.ru
 Marat  Shamsiev,  2:5093/14.2
 Anatoly  Podgoretsky,  anatoly@podgoretsky.com
 Vjacheslav  Trushkin,  trushkin@europe.com
 Stas  Malinovski,  stasm@tsl.ru
 Kazantsev  Alexey,  kazav@vngdu.udmurtneft.ru
 Andrey  Belyakov,  andrejb@netmail.lv
 Andrew  V.  Fionik,  fionika@papillon.ru
 Tolik  Tentser,  tt@katren.ru
 Roman  Timofeew,  roman@kavkaz.elektra.ru
 Dennis  Prochko,  sysadmin@farmeko.khv.ru
 Алексей,  lexx@basegroup.ru
 Vladimir  Hmelyoff,  2:5055/115.61
 Sergey  Grebenyuk,  2:468/57.333
 Philip  A.  Milovanov,  milovanov@diagnostic.ru
 Oleg  Chensky,  chensky@grot.de
 Vladimir  Vassiliev,  voldemar@mkb.mari.ru
 Gavrilo,  gavrilo@dnepro.kharkov.ua
 Stepan  F.Mitish,  step@abaddon.ntu-kpi.kiev.ua
 Alexey  Goloborchy,  golalex@bicom.ru
 Alexander  V.  Gaiduk,  gav@lesobank.ru
 Yury  Sinegubov,  2:5006/1
 Andrei  N.  DUBIK,  sland@e-mail.pl.ua

I-30: Преамбула

 Пожалуйста,  воздержитесь  от  задавания  вопросов  в  конференции
 RU.DELPHI.INTERNET,  до  того,  как  прочтете  этот  документ,  правила
 конференции,  ознакомитесь  со  списком  рекомендованной  литературы
 и  проведете  самостоятельные  исследования  вопроса.  Это  поможет
 всем  нам  сохранить  на  должном  высоком  уровне  соотношение  полезной
 и  бесполезной  информации  и  разгрузить  конференции  от  бесполезного  трафика.

I-40: О поле Subject

 Правилами  иерархии,  в  частности,  регламентируется  содержание
 поля  Subject  ваших  писем.  Дело  в  том,  что  довольно  большое
 количество  "потенциально  полезных  вам  индивидумов"  читают  эхи
 методом  "по  сабджектам",  сознательно  не  тратя  время  на  письма
 под  заголовком  "Help!",  "Проблема"  или  "Вопрос  чайника".  В  данном
 случае  использование  комбинации  клавиш  Shift-1  лишь  усугубляет
 ваше  положение.  Подумайте  об  этом.
 
 Не  указание  же  заголовка  вообще  может  вызвать  законный  вопрос
 "ТЫ  МЕНЯ  УВАЖАЕШЬ",  так  здесь  явное  неуважение  к  читателям
 конференции,  не  хватило  даже  сил  на  написание  заголовка,  то
 какое  право  на  получение  ответа,  лень  написать  заголовок,  так
 остальным  будет  лень  отвечать.

I-50: Что НЕ рекомендуется:

 *  обсуждение  вопросов,  относящихся  к  базам  данных  -  существует
 конференция  RU.DELPHI.DB.
 
 *  обсуждение  вопросов,  относящихся  к  отчетам  -  существует
 конференция  RU.DELPHI.REPORTS.
 
 *  обсуждение  общих  программирования  на  Delphi  -  существует
 родоначальная  конференция  RU.DELPHI.
 
 *  обсуждение  вопросов  вида  "А  что  такое  Delphi?",  "Что  такое
 Интернет?".Существуют  конференции  RU.DELPHI.CHAINIK  и
 RU.INTERNET.CHAINIK.
 
 !  К  сожалению,  мотивация  типа  "мой  аплинк/провайдер  не  получает
 эту  эху/ньюсгруппу"  в  данном  случае  не  принимается,  потому  что
 за  продолжительное  время,  прошедшее  с  момента  создания  этих
 конференций,  следовало  бы  подумать  в  первую  очередь  о  себе  и
 создать  для  себя  необходимое  количество  каналов  поступления
 информации.
 
 *  обсуждение  Вашей  совершенно  новой  и  безумно  свежей  идеи  о
 том,  что  эху  пора  разделить  на  две/три/больше  частей,  потому  что
 читать  ее  нет  никаких  сил.  Вы  даже  не  в  первой  сотне  придумавших
 и  успешно  высказавших  сие.  От  себя  могу  посоветовать  пользоваться
 хорошими  программами  для  чтения  эхо-конференций.
 
 *  обсуждение  тем,  не  связанных  с  програмированием  на  Delphi:
 алгоритмы,  общие  вопросы  программирования  под  Win32,  общие
 организационные  вопросы,  связанные  с  разработкой  программного
 обеспечения,  etc.
 
 *  общая  неспособность  получать  информацию  из  окружающей
 реальности  также  не  приветствуется.  Прочтите  книгу  об  эффективной
 коммуникации  и  должном  отношении  ко  всему.

I-60: Изменения и дополнения к документу. Распространение документа.

 Этот  документ  регулярно  изменяется  в  результате  отслеживания
 происходящего  в    RU.DELPHI.INTERNET.  Вы  можете  поучаствовать
 в  составлении  документа,  прислав  по  адресу  2:463/482.25  -  Den  Krep  
 )  сформулированный  вариант  вопроса,  ответ  или  
 дополнение  или  исправление  к  ответу.  Довольно  важным  критерием  
 отбора  ответов  является  размер.  Я  не  хочу  публиковать  большие  куски  
 кода,  предпочитая  давать  указание  на  источник  дополнительной
 информации  или  направление  самостоятельных  разработок.  В  любом
 случае,  Вы  можете  обратиться  к  авторам  сопутствующих  проектов,
 список  которых  приведен  ниже.
 
 Все  здравомыслящие  люди  ошибаются  -  не  ошибаются  только
 дураки.  Ведущий  данного  FAQ  и  уважаемые  авторы  ответов  на
 вопросы  тоже  не  безгрешны  и  могут  ошибиться.  Поэтому,  любые
 исправления/дополнения/примечания  к  данному  документу  будут
 с  радостью  приняты  по  вышеозначенным  адресам.  Hе  следует
 шумно  обсуждать  огрехи  авторов  в  конференции  -  не  суди  да  и
 не  осудим  будешь.
 
 Данный  документ  доступен  в  конференции  RU.DELPHI.INTERNET
 (регулярная  отправка  раз  в  неделю  по  воскресеньям).  В
 Интернете  организован  центральный  репозиторий  для  всех  FAQ
 из  иерархии  fido7.ru.delphi.*,  находится  по  адресу
 http://www.podgoretsky.com  или  http://nps.vnet.ee  (доступны
 исходные  тексты  движка,  движок  FaqMaker.exe  и  последнии
 версии  баз).  Альтернативный  репозиторий,  но  имеющий  более
 широкое  назначение  (не  только  иерархии  fido7.ru.delphi.*)
 расположен  по  адресу  http://faq.delphiplus.org,  хотя  там  и
 более  быстрый  хостинг,  но  информация  может  быть  менее
 актуальной.
 
 Также  последняя  версия  FAQ  доступна  по  следующим  адресам:
 http:/daywer.by.ru/fido/ru.delphi.internet.zip
 и
 http://daywer.by.ru/fido/ru.delphi.internet.txt.zip
 
 Разрешается  свободное  распространение  и  использование  этого
 документа  при  соблюдении  определенной  вежливости  по  отношению
 к  автору  и  читателям,  основной  составляющей  чего  является
 соблюдение  целостности  документа.  Hе  очень  приветствуется
 выкладывание  копий  этого  документа  на  WWW:  подумайте,
 нужны  ли  вам  непрерывные  усилия  по  синхронизации?
 
 Если  же  вы  вынуждены  использовать  этот  документ  на  сайте,
 для  того,  чтобы  создать  его    содержимое,  подумайте,  нужен
 ли  вообще  ваш  сайт?
 
 Остерегайтесь  подделок.

I-70: Рекомендуемые источники информации.

 Прежде  всего,  конечно  же,  книги.  Как  бы  это  странно  ни
 звучало,  но  зайдите  в  книжный  магазин  и  купите  себе  там
 какую-нибудь  книгу,  даже  если  она  уже  у  Вас  есть.  Следует
 сразу  предупредить,  что  специфика  современного  российского
 книгоиздания  такова,  что  существует  довольно  большое
 количество  книг,  не  стоящих  своих  денег.  Вероятно,  Вам
 следует  положиться  на  собственное  чутье  и  тщательно  изучить
 предлагаемую  продукцию.
 
 Список  литературы  на  все  интересующие  темы,  рекомендованный
 к  прочтению,  находится  в  неофициальном  FAQ  эхоконференции
 RU.BOOKS.COMPUTING.  Свежие  версии  этого  FAQ  регулярно
 публикуются  в  соответствующей  эхоконференции.
 
 Учтите,  что  кроме  книг  по  Delphi  вас  могут  интересовать
 также  издания,  посвященные  программированию  под  Windows
 и  проектированию  баз  данных.  Delphi,  в  сущности,  является
 обычным  компилятором  для  Windows,  и  довольно  большое
 количество  вопросов,  которые  у  вас  возникнут,  будут  не  столь
 уж  сильно  ориентированы  именно  на  Delphi.  В  свете  тематики
 данного  FAQ  Вас  также  должны  заинтересовать  книги,
 посвященные  функционированию  сети  Internet  и  программированию
 для  этой  сети.
 
 Само  собой,  хотелось  бы  увидеть  у  активного  участника
 конференции  определенные  знания  языка  программирования
 Object  Pascal,  являющегося  основой  Delphi,  а  также  знаний
 в  области  программирования  вообще,  программирования
 под  Windows  в  частности,  а  также  предметной  области  своей
 собственной  задачи.  Без  всякого  сомнения,  вы  можете  общаться
 и  задавать  вопросы  на  любом  уровне,  но  ожидайте
 соответствующей  реакции  извне.
 
 Hаучитесь  также  пользоваться  системой  помощи,  поставляемой
 вместе  с  Delphi.  Как  это  ни  прискорбно,  весьма  ощутимый
 процент  задаваемых  в  эхе  вопросов  легко  снимается
 нажатием  кнопки  F1  и  поиском  примерного  перевода
 вопроса  на  английский  язык.  Примером  тому  может  являться
 сакраментальный  вопрос  о  получении  короткого  имени  файла
 из  длинного  и  ответ:  GetShortPathName.  Да,  скорее  всего  вам
 придется  восполнить  свои  пробелы  в  школьном  образовании
 и  изучить  некоторое  подмножество  английского  языка,  без  коего
 вы  имеете  не  столь  много  шансов  успешно  функционировать  в
 выбранной  области.
 
 Учтите  наличие  в  поставке  Delphi  большого  количества
 разнообразных  примеров.  Возможно,  ознакомившись  с  ними,
 вы  приобретете  дополнительные  знания.  Изучите  исходные
 тексты  Visual  Component  Library,  поставляемой  вместе  с
 Delphi  Professional  и  Delphi  Client/Server,  а  также  хорошие
 образцы  кодирования  и  проектирования,  например,  исходники
 rxLib.
 
 Возможно,  вам  следует  приобрести  тем  или  иным  способом
 ту  часть  Microsoft  Developer  Network  (MSDN),  что  содержит
 в  себе  документацию.  Это  диски  с  названиями  "Platform  SDK",  
 "Additional  SDKs  and  Tools"  и  "DDKs".  В  них  содержится  более
 свежая,  более  полная  и  обширная  информация  по  всем
 аспектам  программирования  под  Windows.  Подписка  на
 эту  часть  MSDN  (это  первый  уровень)  стоит  не  столь
 дорого  и  вы  имеете  все  шансы  купить  ее,  например,  для
 своей  организации.  Более  того,  на  http://msdn.microsoft.com
 можно  получить  доступ  к  львиной  доле  документации  из  MSDN.
 
 Множество  качественной  информации,  относящейся  к
 программированию  под  Windows  95/NT,  можно  получить
 на  http://www.sysinternals.com.  Hа  http://www.iarchitect.com
 находится  большой  ресурс,  посвященный  вопросам  построения
 пользовательского  интерфейса.  Hа  сайте  http://www.perl.org.ru
 содержится  информация,  посвященная  CGI-программированию,
 а  на  сайте  http://www.webclub.ru  можно  найти  массу  полезной
 информации  о  сети  Internet.
 
 Документы  RFCxxxx  можно  найти  на  сайте  Internet  Engineering  Task  Force  
 http://www.ietf.org/.  Либо  на  страничке  rfc-editor'а  http://www.rfc-editor.org
 
 
 По  возможности  фидошные  обитатели  RU.DELPHI  помещают
 интересные  файлы  в  так  называемые  файлэхи.  Официальной
 файлэхой  RU.DELPHI  является  WDEVDELPHI.  Ценным  ресурсом
 являются  файлэхи  группы  FED*  (модератор  --  Акжан  Абдулин,
 2:5040/55).  Если  вы  читаете  RU.DELPHI  из  Фидо,  то  подпишитесь
 на  эти  файлэхи  и  научитесь  пользоваться  файловыми  запросами
 (FReq'ами),  так  как  многие  узлы  хранят  файлы,  проходившие
 по  файлэхам,  в  течение  довольно  долгого  времени.
 Обратитесь  к  вашему  боссу  в  случае  затруднений.  Если
 же  Вы  из  Интернета,  то  поисковые  машины,  такие  как
 http://www.altavista.com,  http://ftpsearch.lycos.com,  а  также
 крупнейший  архив  ньюсгрупп  http://www.dejanews.com,
 станут  вашими  лучшими  помощниками.  Вам  следует
 также  заметить,  что  существует  определенное  количество
 FTP-архивов,  содержащих  вышеупомянутые  файлэхи,
 например,  ftp://bbs.ogo.ru.
 
 Само  собой,  Интернет  переполнен  ресурсами,  посвященными
 Borland  Delphi.  Для  начала  хороший  список  ссылок  можно
 найти  на  официальной  странице  rxLib:  http://www.rxlib.com.
 
 Очень  полезным  ресурсом  является  Delphi  Bug  List,  лежащий
 по  адресу  http://www.dataweb.net/~r.p.sterkenburg.  Это
 список  ошибок  во  всех  известных  версиях  Delphi,  адекватно
 обновляемый.
 
 В  FIDO  вы  можете  подписаться  на  дружественные  эхи,  такие  как:
 
           RU.CBUILDER  -  Borland  C++Builder;
           RU.CGI;
           RU.INTERNET.SOFT  -  программное  обеспечение  для  Internet;
           RU.INTERNET.TECHNOLOGY;
           SU.WINDOWS.PROG  -  общие  вопросы  программирования  под  MS  Windows;
           SU.WIN32.PROG  -  вопросы  программирования  для  Win32  API;
           SU.WIN95.PROG  -  вопросы  программирования  под  MS  Windows  95;
           SU.DBMS  -  базы  данных;
           SU.DBMS.SQL  -  SQL-базы  данных;
           SU.DBMS.BORLAND  -  базы  данных  фирмы  Borland;
           SU.DBMS.INTERBASE  -  "родная"  для  Delphi  база  данных;
           SU.SOFTW  -  общие  вопросы  разработки  программ;
           RU.ALGORITHMS  -  вещи,  не  зависящие  от  фамилии  президента  IBM  и
 текущего  номера  сервиспака  к  NT;
           SU.FLAME  -  обсуждение  превосходства  Borland  Delphi  над  всеми
 прочими  средствами  разработки.

Q-80: Что мне нужно, чтобы писать приложения для Internet или использующие Internet для передачи данных?

 Прежде  всего,  Вам  нужно  иметь  хотя  бы  небольшое  представление  о  самой  Internet.
 
 Также,  Вам  нужна  Delphi  Enterprise,  которая  содержит  все  необходимые  компоненты  и  исходники.
 
 Также,  для  отладки  приложений,  Вам  может  понадобится
 установить  на  своем  компьютере  Internet-сервер.  Hаиболее
 популярный  сервер  для  *NIX  -  Apache,  имеется  также  и  в
 реализации  для  Windows.  Я  использую  Xitami  Server,  который
 можно  бесплатно  загрузить  на  http://www.imatrix.com.

Q-90: Хочу сделать WEB-Browser. Что делать?

 Существует  Active-X  компонент  TWebBrowser  -  это  тот  же  самый,  что  используется  в  MS  IE.
 
 Компонент  из  Netscape  Navigator  также  можно  поместить  на  форму,  подробности  на  http://www.chami.com/tips/delphi/103096D.html
 
 Еще  на  http://www.pbear.com  лежат  THTMLViewer  и  TFrameViewer.

Q-100: Я хочу работать с протоколами HTTP, FTP...

 Для  этих  целей  предназначены  компоненты  TNMFTP,  TNMHTTP.
 
 См.  также  Q46,  Q47
 
 DK:  Можно  также  посмотреть  в  сторону  компонент  TServerSocket,  TClientSocket  
 и  документов  RFC2616  (HTTP1.1),  RFC1945  (HTTP1.0),  RFC765  (FTP)

Q-110: Я хочу отправлять из моего приложения электронную почту по протоколам SMTP, POP3...

 В  D5  Вы  можете  попробовать  использовать  компоненты  TNMSMTP  и  TNMPOP3,
 в  D6  и  Kylix  компоненты  от  NetMasters  заменены  компонентами  Indy.
 
 Алгоритм  простой  (для  сторонних  компонентов  он  принципиально  ничем  не  отличается):
 -  необходимо  заполнить  структуру  PostMessage;
 -  отправить  эту  структуру  при  помощи  метода  SendMail.
 
 Структура  PostMessage:
 (*)  FromName:  string  -  имя  отправителя;
 FromAddress:  string  -  Почтовый  адресс  отправителя
 ReplyToAddress:  string  -  Адрес,  по  которому  следует  ответить  на  письмо;
 Organization:  string
 LocalProgram:  string  -  Имя  почтовой  программы  отправителя;
 (*)  ToAddress:  TStringList  -  Почтовый  адрес  главного  получателя  (ей)
 ToCC:  TStringList  -  Список  получателей  Carbon  Copy
 ToBCC:  TSringList  -  Список  получателей  Blind  Carbon  Copy
 Attachments:  TStringList  -  Список  вложений
 Body:  TStringList  -  Собственно  текст  письма
 Subject:  string  -  Строка  темы  письма.
 (*)  -  помечены  обязательные  поля
 С  остальным  не  сложно  разобраться  самому.
 
 -----------------------------------
 
 Также  это  можно  сделать  при  помощи  MAPI.  
 Т.е.  письмо  будет  отправлено  средствами  _почтовой_программы_по_умолчанию_  -  со  всеми  недостатками  :)  (например  письмо  будет  помещено  в  папку  "отправленные").  Зато  без  всяких  там  компонент  и  просто  :)
 
 Hиже  готовая  функция,  в  которой:
 From  -  от  кого
 Dest  -  кому
 Subject  -  тема
 Text  -  текст  письма
 FileName  -  путь  к  вложению  (если  '',  то  соответственно  ничего  и  не  вкладываем)
 Outlook  -  показывать  или  нет  письмо  перед  отправкой  (в  твоём  случае  False)
 
 Uses  MAPI;
 ...
 function  SendMail(const  From,  Dest,  Subject,  Text,  FileName:  PChar;
 Outlook:  boolean):Integer;
 var
     Message:  TMapiMessage;
     Recipient,  Sender:  TMapiRecipDesc;
     File_Attachment:  TMapiFileDesc;
                                                                                                                               
     function  MakeMessage:  TMapiMessage;
     begin
         FillChar(Sender,  SizeOf(Sender),  0);
         Sender.ulRecipClass  :=  MAPI_ORIG;
         Sender.lpszAddress  :=  From;
                                                                                               
         FillChar(Recipient,  SizeOf(Recipient),  0);
         Recipient.ulRecipClass  :=  MAPI_TO;
         Recipient.lpszAddress  :=  Dest;
 
         FillChar(File_Attachment,  SizeOf(File_Attachment),  0);
         File_Attachment.nPosition  :=  Cardinal(-1);
         File_Attachment.lpszPathName  :=  FileName;
 
         FillChar(Result,  SizeOf(Result),  0);
         with  Message  do  begin
             lpszSubject  :=  Subject;
             lpszNoteText  :=  Text;
             lpOriginator  :=  @Sender;
             nRecipCount  :=  1;
             lpRecips  :=  @Recipient;
             nFileCount  :=  1;
             lpFiles  :=  @File_Attachment;
         end;
     end;
 
 var
     SM:  TFNMapiSendMail;
     MAPIModule:  HModule;
     MAPI_FLAG:  Cardinal;
 begin
     if  Outlook  then
       MAPI_FLAG:=MAPI_DIALOG
     else
       MAPI_FLAG:=0;
     MAPIModule  :=  LoadLibrary(PChar(MAPIDLL));
     if  MAPIModule  =  0  then
         Result  :=  -1
     else
         try
             @SM  :=  GetProcAddress(MAPIModule,  'MAPISendMail');
             if  @SM  <>  nil  then  begin
                 MakeMessage;
                 Result  :=  SM(0,  Application.Handle,  Message,  MAPI_FLAG,  0);
             end  else  Result  :=  1;
         finally
             FreeLibrary(MAPIModule);
         end;
 end;

Q-120: Мне надо реализовать обмен данными между двумя удаленными машинами (переслать файл).

 Удобнее  всего  будет  сделать  это  при  помощи  сокетов.
 
 В  Delphi  есть  компоненты  TClientSocket  и  TServerSocket,  реализующие,
 соответственно,  клиентский  и  серверный  сокеты.  Также,  Вы  можете  использовать
 функции  API  WinSock  напрямую  -  их  заголовки  находятся  в  файле  winsock.pas.
 Однако,  на  мой  взгляд,  использование  компонентов  намного  удобнее.
 
 Также  можно  использовать  входящие  в  поставку  Delphi  Enterprise  компоненты
 фирмы  NetMasters  -  это  TNMMsgServ  и  TNMMsg  (серверная  и  клиентская  части;
 компоненты  предназначены  для  обмена  текстовыми  сообщениями),  TNMStrmServ  и
 TNMStrm  (серверная  и  клиентская  части;  компоненты  предназначены  для  обмена
 потоками  данных),  а  также  TNMUDP,  компонент,  реализующий  протокол  UDP  (User
 Datagrem  Protocol,  см.  также  RFC768).

Q-130: Как мне сделать обмен данными (файлами), как в Napster'е?

 Посмотри  спецификацию  протокола  на
 http://slavanap2.sourceforge.net/nap.txt  или
 http://opennap.sourceforge.net/napster.txt
 
 Также  есть  следующие  исходники:
 -  SlavaNap  (Delphi  4)  http://slavanap2.sourceforge.net
 -  OpenNap  (C,  console  app)  http://opennap.sourceforge.net
 -  TekNap  (C,  console  app)  http://www.teknap.com
 Возможно,  что  существуют  другие  исходники.  Это  можно  выяснить  в
 napigator  форумах  (http://forums.napigator.com)
 
 Кроме  того  есть  mailing  list  для  разработчиков
 napster-совместимых  программ:
 http://www.onelist.com/community/napdev
 Там  также  есть  архив  группы  napdev.
 Или  пошли  пустое  письмо  на  napdev-subscribe@yahoogroups.com

Q-140: А что такое сокет?

 Существует  мировой  стандарт  структуры  протоколов  связи  -
 семиуровневая  OSI  (Open  Systems  Interface  -  интерфейс
 открытых  систем).  Hа  каждом  из  уровней  этой  структуры
 решается  свой  объем  задач  своими  методами.  Сокеты
 находятся  на  так  назывемом  транспортном  уровне  -  ниже
 находится  сетевой  протокол  IP,  выше  -  специализированные
 протоколы  сеансового  уровня,  ориентированные  на  решение
 конкретных  задач  -  это  всем  известные  FTP,  SMTP,  etc.
 
 Если  смотреть  по  сути,  сокет  -  это  модель  одного  конца
 сетевого  соединения,  со  всеми  присущими  ему  свойствами,
 и,  естественно  -  возможностью  получать  и  передавать
 данные.  По  содержанию  -  это  прикладной  программный
 интерфейс,  входящий  в  состав  многих  ОС.  В  семействе
 Windows  -  начиная  с  версии  3.11,  и  носит  название  WinSock.
 Прототипы  функций  WinSock  API  находятся  в  файле
 winsock.pas.  В  Delphi  есть  полноценная  инкапсуляция
 клиентского  и  серверного  сокетов,  представленная
 компонентами  TClientSocket  и  TServerSocket,  находящимися
 на  закладке  Internet.
 
 Сокеты  не  обязательно  базируются  на  протоколе  TCP/IP,  они  могут  также  базироваться  на  IPX/SPX,  etc.
 
 Также  Вам  следует  ознакомиться  со  списком  зарезервированных  номеров  портов.
 
 Механизм  взаимодействия  сокетов  таков.  С  одной  из  двух
 сторон  запускается  серверный  сокет,  который  сразу  после
 запуска  находится  в  режиме  прослушивания  (listening),  точнее  -
 ожидания  запросов  от  клиентов.  После  получения  запроса  от
 клиента  устанавливается  связь,  и  создается  новый  экземпляр  серверного  сокета.
 
 Так  как  работа  с  сокетами,  это,  по  сути  -  операции  ввода/вывода,
 которые  бывают  синхронными  или  асинхронными,  то  и  тип
 работы  сокета  обладает  бывает  синхронным  или  асинхронным.
 Компоненты  TClientSock  и  TServerSock  поддерживают  оба  режима  работы.
 
 Дополнение  от  Анатолия  Подгорецкого:
 
 Когда  говорят  СОКЕТ  то  часто  не  представляют,  что  это  такое.
 Можно  говорить  об  моделях,  об  реализациях  и  так  далее.  Но  есть
 одно  простое  толкование,  применимое  для  протокола  IP.  Как
 известно  для  взаимодействия  между  машинами  по  протоколу
 IP  используются  адреса  и  порты.
 
 Первое  на  текущий  момент  представляют  из  себя  32-x
 битный  адрес,  наиболее  часто  его  представляют  в  символьной
 форме  mmm.nnn.ppp.qqq  (адрес  разбитый  на  четыре  октета
 по  одному  байту  в  октете  и  разделеный  точками)  .
 
 Второе  -  это  номер  порта  в  диапазоне  от  нуля  до  65535
 
 Так  вот  эта  пара  и  есть  сокет  (гнездо  в  в  котором  расположены
 адрес  и  порт).
 
 В  процессе  обмена  как  правило  используются  два  сокета  -
 сокет  отправителя  и  сокет  получателя.
 
 Например  при  обращении  к  моему  серверу  на  HTTP  порт
 сокет  будет  выглядеть  так:  194.106.118.30:80,  а  ответ  будет  поступать  на  mmm.nnn.ppp.qqq:xxx

Q-150: Hужно сканировать порты через сокс-прокси сервер. Как это сделать?

 Описание  протокола  SOCKS5  см.  в  RFC1928:  http://www.faqs.org/rfcs/rfc1928.html
 
 Хотя  проще  запустить  уже  готовый  сканер  портов  из-под  SocksCap  или  e-Border  Client  (www.socks.nec.com)

Q-160: У меня ни TServerSocket, ни TClientSocket без scktsrvr.exe отказываются работать.

 Вопрос:  У  меня  ни  TServerSocket,  ни  TClientSocket  без  scktsrvr.exe  отказываются  работать!  Слышал,  что  для  решения  проблемы  можно  что-то  откуда-то  вырезать  и  вклеить  в  программу.
 
 Установите  этот  компонент:
 
 *--*  sck.pas  *--*
 unit  Sck;
 
 interface
 
 uses
     Classes,  SysUtils,  Windows,  Messages,
     ScktComp,  SConnect,  ActiveX,  MidConst;
 
 type
     TNotifyClient  =  procedure  (Sender:  TObject;  Thread:  TServerClientThread)  of
 object;
 
 {  TSocketDispatcher  }
     TSocketDispatcher  =  class;
 
 {  TSocketDispatcherThread  }
     TSocketDispatcherThread  =  class(TServerClientThread,  ISendDataBlock)
     private
         FRefCount:  Integer;
         FInterpreter:  TDataBlockInterpreter;
         FTransport:  ITransport;
         FInterceptGUID:  string;
         FLastActivity:  TDateTime;
         FTimeout:  TDateTime;
         FRegisteredOnly:  Boolean;
     protected
         SocketDispatcher:  TSocketDispatcher;
         function  CreateServerTransport:  ITransport;  virtual;
         procedure  AddClient;
         procedure  RemoveClient;
         {  IUnknown  }
         function  QueryInterface(const  IID:  TGUID;  out  Obj):  HResult;  stdcall;
         function  _AddRef:  Integer;  stdcall;
         function  _Release:  Integer;  stdcall;
         {  ISendDataBlock  }
         function  Send(const  Data:  IDataBlock;  WaitForResult:  Boolean):  IDataBlock;
 stdcall;
     public
         constructor  Create(AOwner:  TSocketDispatcher;  CreateSuspended:  Boolean;
             ASocket:  TServerClientWinSocket;  const  InterceptGUID:  string;
             Timeout:  Integer;  RegisteredOnly:  Boolean);
         procedure  ClientExecute;  override;
         property  LastActivity:  TDateTime  read  FLastActivity;
     end;
 
 {  TSocketDispatcher  }
     TSocketDispatcher  =  class(TServerSocket)
     private
         FInterceptGUID:  string;
         FTimeout:  Integer;
         FRegisteredOnly:  Boolean;
         FOnRemoveClient:  TNotifyClient;
         FOnAddClient:  TNotifyClient;
         procedure  GetThread(Sender:  TObject;  ClientSocket:  TServerClientWinSocket;
             var  SocketThread:  TServerClientThread);
     published
         constructor  Create(AOwner:  TComponent);  override;
         property  InterceptGUID:  string  read  FInterceptGUID  write  FInterceptGUID;
         property  Timeout:  Integer  read  FTimeout  write  FTimeout;
         property  RegisteredOnly:  Boolean  read  FRegisteredOnly  write  FRegisteredOnly;
         property  OnAddClient:  TNotifyClient  read  FOnAddClient  write  FOnAddClient;
         property  OnRemoveClient:  TNotifyClient  read  FOnRemoveClient  write
 FOnRemoveClient;
     end;
 
 procedure  Register;
 
 implementation
 
 procedure  Register;
 begin
     RegisterComponents('Midas',  [TSocketDispatcher]);
 end;
 
 {  TSocketDispatcherThread  }
 
 constructor  TSocketDispatcherThread.Create(AOwner:  TSocketDispatcher;
     CreateSuspended:  Boolean;  ASocket:  TServerClientWinSocket;
     const  InterceptGUID:  string;  Timeout:  Integer;  RegisteredOnly:  Boolean);
 begin
     SocketDispatcher  :=  AOwner;
     FInterceptGUID  :=  InterceptGUID;
     FTimeout  :=  EncodeTime(Timeout  div  60,  Timeout  mod  60,  0,  0);
     FLastActivity  :=  Now;
     FRegisteredOnly  :=  RegisteredOnly;
     inherited  Create(CreateSuspended,  ASocket);
 end;
 
 function  TSocketDispatcherThread.CreateServerTransport:  ITransport;
 var
     SocketTransport:  TSocketTransport;
 begin
     SocketTransport  :=  TSocketTransport.Create;
     SocketTransport.Socket  :=  ClientSocket;
     SocketTransport.InterceptGUID  :=  FInterceptGUID;
     Result  :=  SocketTransport  as  ITransport;
 end;
 
 procedure  TSocketDispatcherThread.AddClient;
 begin
     with  SocketDispatcher  do
         if  Assigned(OnAddClient)  then  OnAddClient(SocketDispatcher,  Self);
 end;
 
 procedure  TSocketDispatcherThread.RemoveClient;
 begin
     with  SocketDispatcher  do
         if  Assigned(OnRemoveClient)  then  OnRemoveClient(SocketDispatcher,  Self);
 end;
 
 {  TSocketDispatcherThread.IUnknown  }
 
 function  TSocketDispatcherThread.QueryInterface(const  IID:  TGUID;
     out  Obj):  HResult;
 begin
     if  GetInterface(IID,  Obj)  then  Result  :=  0  else  Result  :=  E_NOINTERFACE;
 end;
 
 function  TSocketDispatcherThread._AddRef:  Integer;
 begin
     Inc(FRefCount);
     Result  :=  FRefCount;
 end;
 
 function  TSocketDispatcherThread._Release:  Integer;
 begin
     Dec(FRefCount);
     Result  :=  FRefCount;
 end;
 
 {  TSocketDispatcherThread.ISendDataBlock  }
 
 function  TSocketDispatcherThread.Send(const  Data:  IDataBlock;
     WaitForResult:  Boolean):  IDataBlock;
 begin
     FTransport.Send(Data);
     if  WaitForResult  then
         while  True  do
         begin
             Result  :=  FTransport.Receive(True,  0);
             if  Result  =  nil  then  break;
             if  (Result.Signature  and  ResultSig)  =  ResultSig  then
                 break  else
                 FInterpreter.InterpretData(Result);
         end;
 end;
 
 procedure  TSocketDispatcherThread.ClientExecute;
 var
     Data:  IDataBlock;
     msg:  TMsg;
     Obj:  ISendDataBlock;
     Event:  THandle;
     WaitTime:  DWord;
 begin
     CoInitialize(nil);
     try
         Synchronize(AddClient);
         FTransport  :=  CreateServerTransport;
         try
             Event  :=  FTransport.GetWaitEvent;
             PeekMessage(msg,  0,  WM_USER,  WM_USER,  PM_NOREMOVE);
             GetInterface(ISendDataBlock,  Obj);
             if  FRegisteredOnly  then
                 FInterpreter  :=  TDataBlockInterpreter.Create(Obj,  SSockets)  else
                 FInterpreter  :=  TDataBlockInterpreter.Create(Obj,  '');
             try
                 Obj  :=  nil;
                 if  FTimeout  =  0  then
                     WaitTime  :=  INFINITE  else
                     WaitTime  :=  60000;
                 while  not  Terminated  and  FTransport.Connected  do
                 try
                     case  MsgWaitForMultipleObjects(1,  Event,  False,  WaitTime,
                       QS_ALLEVENTS)  of
                         WAIT_OBJECT_0:
                         begin
                             WSAResetEvent(Event);
                             Data  :=  FTransport.Receive(False,  0);
                             if  Assigned(Data)  then
                             begin
                                 FLastActivity  :=  Now;
                                 FInterpreter.InterpretData(Data);
                                 Data  :=  nil;
                                 FLastActivity  :=  Now;
                             end;
                         end;
                         WAIT_OBJECT_0  +  1:
                             while  PeekMessage(msg,  0,  0,  0,  PM_REMOVE)  do
                                 DispatchMessage(msg);
                         WAIT_TIMEOUT:
                             if  (FTimeout  >  0)  and  ((Now  -  FLastActivity)  >  FTimeout)  then
                                 FTransport.Connected  :=  False;
                     end;
                 except
                     FTransport.Connected  :=  False;
                 end;
             finally
                 FInterpreter.Free;
                 FInterpreter  :=  nil;
             end;
         finally
             FTransport  :=  nil;
         end;
     finally
         CoUninitialize;
         Synchronize(RemoveClient);
     end;
 end;
 
 
 {  TSocketDispatcher  }
 
 constructor  TSocketDispatcher.Create(AOwner:  TComponent);
 begin
     inherited  Create(AOwner);
     ServerType  :=  stThreadBlocking;
     OnGetThread  :=  GetThread;
 end;
 
 procedure  TSocketDispatcher.GetThread(Sender:  TObject;
     ClientSocket:  TServerClientWinSocket;
     var  SocketThread:  TServerClientThread);
 begin
     SocketThread  :=  TSocketDispatcherThread.Create(Self,  False,  ClientSocket,
         InterceptGUID,  Timeout,  RegisteredOnly);
 end;
 
 end.

Q-170: Как пеpесылать файл чеpез nonBlocking socket?

     На  форме  ServerSocket1,  ClientSocket1  :  (Active  :=  False,
     Host  :=  localhost,  Port  :=  2001,  xType  :=  xNonBlocking),
     OpenDialog1,  Button1,  Memo1.
 
 procedure  TfmMain.FormCreate(Sender:  TObject);
 begin
     ServerSocket1.Active:=true;
     ClientSocket1.Active:=true;
 end;
 
 {---  Server  ---}
 
 procedure  TfmMain.Button1Click(Sender:  TObject);
 var
     sStream  :  TMemoryStream;
 begin
     sStream  :=  TMemoryStream.Create;
     if  not  OpenDialog1.Execute  then
         Exit;
     sStream.LoadFromFile(OpenDialog1.FileName);
     ServerSocket1.Socket.Connections[0].SendStreamThenDrop(sStream);
 end;
 
 {---  Client  ---}
 
 const
     MAX_BUF_SIZE  =  $4095;
 
 var
     fStream:  TFileStream;
 
 {OnConnect}
 procedure  TfmMain.ClientSocket1Connect(Sender:  TObject;
     Socket:  TCustomWinSocket);
 begin
     fStream:=  TFileStream.Create('Receive.fil',  fmCreate);
 end;
 
 {OnRead}
 procedure  TfmMain.ClientSocket1Read(Sender:  TObject;
     Socket:  TCustomWinSocket);
 var
     count  :Integer;
     buffer:  Array  [0..MAX_BUF_SIZE]  of  Char;
 begin
     repeat
         Socket.Lock;
         count:=  Socket.ReceiveBuf(buffer,SizeOf(buffer));
         if  count  >  0  then
             fStream.WriteBuffer(buffer,count);
         Socket.Unlock;
       until  (count  <=  0);
 
       Memo1.Lines.Add(IntToStr(fStream.Size));
 end;
 
 {OnDisconnect}
 procedure  TfmMain.ClientSocket1Disconnect(Sender:  TObject;
     Socket:  TCustomWinSocket);
 begin
       fStream.Free;
 end;

Q-180: Хочу получать информацию о дате и времени из Internet.

 Вам  помогут  компоненты  TNMDayTime  и  TNMTime,  которые  (согласно  RFC867  и  RFC868
 соответственно)  и  предназначены  для  этих  целей.

Q-190: При запросе по неверному адресу компонент TNMHTTP виснет или вылетает. Что делать?

 Обработать  событие  OnFailure.

Q-200: Мне надо закодировать данные в UUE (MIME) код.

 Компонент  TNMUUProcessor  станет  Вашим  хорошим  помощником.
 
 Если  Вам  не  хочется  использовать  компоненты  от  NetMasters,  попробуйте
 Indy.  Информацию  о  данном  наборе  компонент  можно  найти  в  этом  FAQ.
 
 Но!  При  получении  писем  (атачей)  в  кoдировке  UUE  компоненты  из
 библиотеки  Indy  работают  не  очень  корректно.  На  http://www.rtfm.be/fpiette
 можно  найти  нужный  файл  pop3cli.zip.
 
 DK:  Можно  также  почитать  о  MIME  в  RFCs  2045-2049  

Q-210: Компоненты на странице FastNet глючат!

 Попробуйте  набор  компонент  Internet  Direct  -  Indy.
 
 Взять  его  можно  на  http://www.nevrona.com/indy

Q-220: Хочу организовать чат. Как?

 В  подкаталоге  DEMOS\INTERNET\CHAT  есть  пример  чата.

Q-230: Ассинхронная ошибка.

 Вопрос:  Почему  не  работает  следующий  код?
 
           begin
               ClietnSocket1.Open;
               if  ClietnSocket1.Socket.Connected  then
                   ClietnSocket1.Socket.SendText('Hello');
               {..}
           end;
           Выдает  -  ассинхронная  ошибка.
 
 Вы  работаете  в  ассинхронном  режиме.  Следует  использовать  соответсвующие
 события.

Q-240: Я слышал, что Delphi позволяет писать CGI-приложения. Так ли это?

 Да,    действительно,  Delphi  позволяет  создавать  CGI-приложения  трех  видов:
 
           *  Stand-alone  CGI  (EXE)
           *  Win-CGI  (EXE)
           *  ISAPI/NSAPI  dynamic  link  library  (DLL)
 
 Рассмотрим  их  подробнее.  Обычное  CGI-приложение  получает
 необходимую  информацию  через  переменные  окружения  и
 STDIN,  а  выводит  -  через  STDOUT.  Понятно,  что  это  в
 условиях  Windows  не  очень  удобно,  зато  100%  работает
 с  любым  сервером  под  Windows,  который  поддерживает  CGI.
 
 Win-CGI  приложение  отличается  тем,  что  информация  передается
 через  INI-файл,  а  выводится  в  файл,  который  затем  сервер
 передает  в  ответ  на  запрос.
 
 ISAPI/NSAPI  Dll  (Internet  Services  API  -  Microsoft  Server)/(Netscape
 Services  API  -  Netscape  Server)  работает  как  обычная  dll.  Она
 загружается  в  адресное  пространство  сервера.  Каждый  запрос
 обрабатывается  в  отдельном  потоке.  Сия  dll  должна  экспортировать
 три  функции  -  GetExtensionVersion,  HttpExtensionProc  и  TerminateExtension.
 
 Основа  этих  приложений  -  классы  TCGIApplication  (для  CGI  и  WinCGI)  и  TISAPIApplication.
 
 Сам  процесс  написания  CGI-приложения  на  Delphi  достаточно  подробно  описан  в  help'е.

Q-250: Как мне отлаживать CGI-приложение?

 Во-первых,  Вам  необходим  установленный  WEB-сервер.
 
 Для  Stand-Alone  CGI  приложений  достаточно  любого  сервера.  Я
 использую  Xitami  server.  ISAPI/NSAPI  Dll  поддерживаются  всеми
 серверами  от  Microsoft,  Netscape  Server  2.0,  а  также  сервером  Apache.
 
 Во-вторых,  это  зависит  от  того,  что  именно  делает  Ваша
 программа.  Если  она  должна  предлагать  пользователю
 заполнить  некую  форму,  то  Вам  нужно  создать  html-файл,
 в  котором  эта  форма  была  бы  описана.  Описывается  форма  тэгом
 
 

:
 
 
 
 

 
 Контролы  на  форму  помещаются  тэгом  :
 
       type="*тип_контрола*"
     name="*имя_контрола*"
     [checked]
     value="*значение*"
     [size="*размер*">
 
 Для  того,  чтобы  получить  нужный  контрол,  см.  значения  свойства  type  в  следующей  таблице:
 
 TEdit                  text
 TCheckBox          checkbox
 TRadioButton    radio
 TButton              submit
 
 Для  получения  контрола  типа  TComboBox  существует  тэг  
     
 
 Для  получение  контрола  типа  TMemo  cуществует  тэг  
 
 Более  подробную  информацию  о  тэгах  Вы  можете  получить,  обратившись  к  соответствующим  источникам.
 
 Далее  напускаете  Ваш  браузер  на  эту  страницу.  Вводите  тестовые  значения  и  нажимаете  кнопку  подтверждения,  после  чего  сервер  запустит  Ваше  приложение.
 
 Если  Вам  не  надо  обрабатывать  формы,  то  просто  укажите  Вашему  браузеру  URL  следующего  вида:
 
 http://127.0.0.1/cgi-bin/yourscript.exe/action?param0=value0¶m1=value1
 
 Слово  'action'  означает  имя  одного  из  компонентов  в  списке
 TWebModule.Actions[Index:  Integer]:  TWebAction.  Параметры,
 следующие  после  вопросительного  знака,  также  необязательны.
 Если  же  они  есть,  то  будут  помещены  после  декодирования  в
 свойство  TWebRequest.QueryFields:  TStrings  и  в  виде  целой
 строки  -  в  свойство  TWebRequest.Query:  String.  Параметр
 Request:TWebRequest  передается  в  обработчик  события  OnAction  компонента  TWebAction.
 
 Также  можно  отлаживать  CGI-приложение  прямо  в  IDE  любым  из  следующих  способов:
 
 0.  Достаточно  запустить  CGI-приложение  один  раз  под  управлением  http  демона.
 Выведите  список  переменных  среды  куда-нибудь  -  в  файл  или  прямо  в  качестве
 ответа  клиенту.  Это  понадобится  исключительно  с  информационной  целью,  для
 справки.
 
 Hа  самом  деле,  для  большинства  тестов  достаточно  только  тех  установок
 переменных  окружения,  которые  непосредственно  используются  в  тестируемой
 вами  части  программы.  В  большинстве  случаев  достаточно  установить  три
 переменные  PATH_INFO,  QUERY_STRING,  METHOD.  Это  можно  сделать  прямо  внутри
 среды  (Kylix  -  Project/Parameters,  Delphi  6  -  Tools\Environment  options)  и
 запускать  приложение  из  среды.  Расставьте  точки  останова  и  наслаждайтесь
 созерцанием  собственных  ошибок.
 
 2.  Только  для  Windows.  Где-нибудь  в  тексте  программы  можно  в  самом  начале
 установить  вывод  на  экран  сообщения  посредством  функции  Windows  API
 MessageBox.  Важно,  чтобы  один  из  параметров  включал  в  себя
 MB_SERVICE_NOTIFICATION.  Запустите  CGI  приложение  штатным  способом  -
 браузер/http  сервер/CGI.  Сразу  после  запуска  программы,  когда  выполнение
 дойдет  до  вызова  MessageBox  на  дисплее  появится  окошко  с  сообщением.  Теперь
 можно  присоединяться  к  процессу,  представляющего  вашу  CGI-программу  из  IDE  -
 Run|Attach  to  process...  Hажмите  кнопочку  на  сообщении,  выданном
 CGI-приложением  и  продолжайте  выполнение,  но  уже  под  управлением
 отладчика  среды.
 
 Возможно,  что  нечто  подобное  покатит  и  для  Linux'а.  Там,  разумеется,  будет  не
 MessageBox  с  MB_SERVICE_NOTIFICATION,  а  что-нибудь  другое.

Q-260: Мое CGI-приложение при обращении к нему ничего не возвращает. Что делать?

 Вопрос:  Мое  CGI-приложение  при  обращении  к  нему,  имеющим  вид,  например,  http://127.0.0.1/cgi-bin/mycgi.exe  ничего  не  возвращает.  Что  делать?
 
 Установите  свойство  TWebAction.Default:  Boolean  в  true  для  той  Action  из  списка,  которая  должна  по  обрабатывать  запросы  тогда,  когда  это  не  делает  ни  одна  из  других  Actions.

Q-270: Бардак с кириллицей в параметрах CGI запроса

 Вопрос:  Я  хочу  реализовать  регистрацию  своей  программы  через
 Internet.  Для  этого  я  вызываю  CGI-скрипт,  которому  в  качестве
 параметра  передается  имя  пользователя.  Однако,  если  имя
 набрано  кириллицей,  происходит  ошибка.  В  чем  дело?
 
 Дело  в  том,  что  при  передаче  запроса  по  протоколу  HTTP
 служебные  символы  и  символы  с  кодами  128..255  надо
 кодировать.  То  есть,  если  пользователь  ввел  имя  'Вася
 Пупкин',  то  запрос  для  регистрации  должен  выглядеть  не  так:
 
           http://site/cgi-bin/reg.pl?user=Вася  Пупкин
 
 а  вот  так:
 
           http://site/cgi-bin/reg.pl?user=%C2%E0%F1%FF+%CF%F3%EF%EA%E8%ED
 
 Решить  проблему  перекодировки  туда  и  обратно  может  компонент  TNMURL.
 
 DK:  Дополнительную  информацию  про  кодирование  URL'ов,  можно  прочитать  в  RFC1738

Q-280: Как отправить письмо, с помощью клиента по умолчанию?

 В  разделе  uses
     ShellAPI.
 
 В  обработчике  OnClick  метки  или  клавиши  ввести  следующий  код.
 
 ShellExecute(Handle,'open','mailto:lalala@lala.ru',nil,nil,SW_SHOWNORMAL);

Q-290: Как открыть страничку с помощью браузера по умолчанию?

 В  разделе  uses
     ShellAPI.
 
 В  обработчике  OnClick  метки  или  клавиши  ввести  следующий  код.
 
 ShellExecute(Handle,'open','http://faq.delphiplus.org',nil,nil,SW_SHOWNORMAL);

Q-300: Как отправить письмо я знаю, а как указать тему, текст сообщения?

 Для  отправки  письма  с  помощью  зарегистрированого  клиента
 используется  функция  Windows  -  ShellExecute,  где  в  качестве
 аргумента  передается  строка  протокола  Mailto.  Для  этого  сделайте  следующее.
 
 по  В  разделе  uses
     ShellAPI.
 
 В  обработчике  OnClick  метки  или  клавиши  ввести  следующий  код.
 
 ShellExecute(Handle,'open','mailto:lalala@lala.ru?par1=value1&par1=value1&...',nil,nil,SW_SHOWNORMAL);
 
 Что  здесь  делается
 
 1.  Вызывается  функция  ShellExecute,  где  третий  параметр  -
 это  строка  в  соответствии  с  протоколом  mailto  и  правилами  оформления  URL
 
 mailto:  -  тип  протокола  (может  быть  http:  в  этом  случае  оставшая  URL  и  параметры  запроса).
 
 lalala@lala.ru  -  адрес  получателя,  можно  включать  несколько  адресов,  разделяя  из  символом  ";"
 
 ?  -  разделитель  параметров  от  адреса
 
 par1=value1  -  имя  параметра  и  его  значение
 
 &  -  разделитель  параметров
 
 Протокол  Mailto  имеет  следующую  форму.
 
       MAILTO:Recipients&Parameters
 
 Поле  Recipients  может  быть  пустым,  одиночным  адресом  и  состоять  из  нескольких  адресов,  разделенных  символом  ";".
 Поле  Parameters  дополнительно  и  если  оно  есть  то  должно
 быть  отделено  символом  "&".  Параметры  должны  появляться
 в  форме  пары  name/value.  Следующий  список  описывает  возможные  параметры:
 
       PARAMETER          DESCRIPTION
 
       CC=                      Carbon  copy  (дополнительные  получатели)
       BCC=                    Blind  carbon  copy  (дополнительные  получатели,  адреса  которых  не  показываются  остальным  получателям)
       SUBJECT=            Subject  text  (тема)
       BODY=                  Body  text  (текст)
 
 Все  данные  указываемые  в  параметрах  должны  быть  так  называемые  Internet  safe  characters.  Используййте  %0d  для  символа  перевод  строки  (LF),  %20  для  пробела  и  так  далее.
 Пример:
 
 mailto:email1;email2?cc=email3&subject=Это%20тема&body=это%20текст%20письма%0dЭто%20другая%20строка

Q-310: Как узнать IP машины по имени?

 uses
     WinSock;
 
 const
     WINSOCK_VERSION  =  $0101;
 
 function  GetIPAddress(Name:String):  string;
 var
     WSAData  :  TWSAData;
     p  :  PHostEnt;
 begin
     WSAStartup(WINSOCK_VERSION,  WSAData);
     p  :=  GetHostByName(PChar(Name));
     Result  :=  inet_ntoa(PInAddr(p.h_addr_list^)^);
     WSACleanup;
 end;

Q-320: Как из ActiveX запросить другую страницу в браузере?

 Смотрите  urlmon.pas  ->  HLinkNavigateString.
 
 К  сожалению,  это  пройдет  только  под  Internet  Explorer.
 
 

Q-330: Какая реализация у ICQ и других Internet-пейджеров?

 Описание  протокола:  http://sophocles.mscom.ru/icq/
 API:  http://www.icq.com/api/

Q-340: Как у TWebBrowser отключить контекстное меню от правой кнопки мыши?

 http://www.compress.ru/Article.asp?id=1127

Q-350: Как узнать домен, к которому я в данный момент подключен? Используется WinNT.

 Использовать  функцию  NetWkstaUserGetInfo,  при  этом  учитывая  две  вещи:
 
 0.  The  set  of  ported  LAN  Manager  functions  supported  by  Microsoft®
 Windows®  is  based  on  the  set  of  LAN  Manager  functions  specified  in
 the  LAN  Manager  2.x  Programmer's  Reference.  They  are  not  a  part
 of  the  Microsoft®  Win32®  application  programming  interface  (API).
 
 Certain  LAN  Manager  functions  are  obsolete.  Other  LAN  Manager
 functions  have  been  superseded.  In  addition,  the  Microsoft®  Windows
 NT®  operating  system  adds  to  the  set  of  networking  functions  introduced
 by  LAN  Manager.
 
 1.  В  Delphi  5  НЕТ  хедера  с  прототипом  этой  функции.  Поэтому  придется
 ее  импортировать  самому.

Q-360: Как из своей программы вызвать диалог изменения настроек Internet?

 uses
     ShellApi;
 
 {...}
 
 ShellExecute(0,  0,  'inetcpl.cpl',...);

Q-370: Как определить наличие соединения c Internet?

 Следует  подключить  модуль  WinInet.pas,  в  котором  есть  замечательная
 функция  InternetGetConnectedState...
 
 Кстати,  в  этом  модуле  имеются  заголовки  еще  массы  других  полезных
 функций.

Q-380: Могут ли передаваться данные из html-страницы в программу (через TWebBrowser)?

 Могyт.  Подpобнее  и  с  пpимеpами  -  зайди  на  стpаницy
 
 http://www.calm.hw.ac.uk/davidf/papers/htmldlg.htm
 
 или
 
 http://sca.uwaterloo.ca/www.calm.hw.ac.uk/davidf/papers/htmldlg.htm

Q-390: Почему при использовании метода TWebBrowser.Navigate нужно указывать полное имя файла?

 В  соответствии  с  RFC  1808  браузер  должен  обрабатывать  URL  вида
 [[[[протокол://]сервер]/][путь/]]страница
 Если  какая-то  часть  пропущена,  браузер  должен  взять  недостающее  из
 текущей  страницы,  или  текущего  URL,  или  из  твоего  приложения.
 
 Поэтому,  для  загрузки  файлов  с  локальных  дисков  нужно  передавать
 методу  TWebBrowser.Navigate  следующее:
 file:///диск:/путь/имя-файла

Q-400: Как хранить web-страницы внутри файла?

 Hа  сайте  http://www.diagnostic.ru/delphi  опубликована  статья  "Сайт  внутри
 EXE  файла".

Q-410: Как определить свой IP адрес?

 uses
     WinSock;
 
 function  GetLocalIP:  String;
 const  WSVer  =  $101;
 var
     wsaData:  TWSAData;
     P:  PHostEnt;
     Buf:  array  [0..127]  of  Char;
 begin
     Result  :=  '';
     if  WSAStartup(WSVer,  wsaData)  =  0  then  begin
         if  GetHostName(@Buf,  128)  =  0  then  begin
             P  :=  GetHostByName(@Buf);
             if  P  <>  nil  then  Result  :=  iNet_ntoa(PInAddr(p^.h_addr_list^)^);
         end;
         WSACleanup;
     end;
 end;

Q-420: Как с помощью Indy работать с Socks Proxy?

 Ответ  для  Indy9.
 
 На  форму  поместить  TIdTCPClient,  TIdIOHandlerSocket,  TIdSocksInfo,
 установить  необходимые  параметры,  связать  между  собой:
 TIdTCPClient.IOHandler  :=  IdIOHandlerSocket1;
 IdIOHandlerSocket.SocksInfo  :=  IdSocksInfo1;
 
 и,  в  принципе,  все.
 
 FAQmaker>  если  кто-то  может  дать  более  развернутый  ответ  на  этот
 FAQmaker>  вопрос,  то,  пожалуйста,  отправьте  мне  его  по  e-mail  -  
 FAQmaker>  будет  использовано  при  обновлении  FAQ

Q-430: Ищу исходники WEB-сервера на Object Pascal

 www.ritlabs.com

Q-440: Как в TWebBrowser организовать изменение размера шрифта?

 procedure  TWebBrowserXXX.SetFontSize(nSize:  OleVariant);
 begin
     if  (nSize  >=  0)  and  (nSize  <=  4)  then
         ExecWB(OLECMDID_ZOOM,  OLECMDEXECOPT_DONTPROMPTUSER,  nSize)
 end;

Q-450: Как перед активацией сокета определить, занят ли на данной машине нужный порт?

 var  SockAddrIn  :  TSockAddrIn;
         FSocket        :  TSocket;
 
     ...
 
     If    bind(FSocket,  SockAddrIn,  SizeOf(SockAddrIn))  <>  0  Then
     begin
         обрабатываем  WSAGetLastError
     end;

Q-460: Как скачать файл, используя proxy?

 DownloadFile('http://some.com/some.zip',  'c:\some.zip');
 
 function  DownloadFile(const  FileURL,  FileName:  String):  Cardinal;
 var
     hSession,  hFile:  HInternet;
     Buffer:  array[1..1024]  of  Byte;
     BufferLen,  fSize:  LongWord;
     f:  File;
 begin
     Result  :=  0;
     hSession  :=  InternetOpen('STEROID  Download',
                                                       INTERNET_OPEN_TYPE_PRECONFIG,  nil,  nil,  0);
     if  Assigned(hSession)  then  begin
         hFile  :=  InternetOpenURL(hSession,  PChar(FileURL),  nil,  0,
                                                           INTERNET_FLAG_RELOAD,  0);
         if  Assigned(hFile)  then  begin
             AssignFile(f,  FileName);
             Rewrite(f,1);
             fSize  :=  0;
             repeat
                 InternetReadFile(hFile,  @Buffer,  SizeOf(Buffer),  BufferLen);
                 BlockWrite(f,  Buffer,  BufferLen);
                 fSize  :=  fSize  +  BufferLen;
             until  (BufferLen  =  0);
             CloseFile(f);
             Result  :=  fSize;
             InternetCloseHandle(hFile);
         end;
         InternetCloseHandle(hSession);
     end;
 end;
 
 Комментарий:
 
 function  InternetOpen(lpszAgent:  PChar;  
                                             dwAccessType:  DWORD;  
                                             lpszProxy,  lpszProxyBypass:  PChar;  
                                             dwFlags:  DWORD):  HINTERNET;  stdcall;
 lpszAgent  
     строка  символов,  которая  передается  серверу  и  идентифицирует
     программное  обеспечение,  пославшее  запрос.
 
 dwAccessType  
     INTERNET_OPEN_TYPE_DIRECT  :  обрабатывает  все  имена  хостов  локально.  
     INTERNET_OPEN_TYPE_PRECONFIG  :  берет  установки  из  реестра.  
     INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY  -  берет  установки  из
         реестра  и  предотвращает  запуск  Jscript  или  Internet  Setup  (INS)
         файлов.  
 !  INTERNET_OPEN_TYPE_PROXY  :  использование  прокси-сервера.
         В  случае  неудачи  использует  INTERNET_OPEN_TYPE_DIRECT.
 
 LpszProxy  -  адрес  прокси-сервера.  Игнорируется  только  если  параметр
         dwAccessType  отличается  от  INTERNET_OPEN_TYPE_PROXY.
 
 LpszProxyBypass  -  список  имен  или  IP-  адресов,  соединяться  с  которыми
         нужно  в  обход  прокси-сервера.  В  списке  допускаются  шаблоны.  Так  же,
         как  и  предыдущий  параметр,  не  может  содержать  пустой  строки.  Если
         dwAccessType  отличен  от  INTERNET_OPEN_TYPE_PROXY,  то  значения
         игнорируются,  и  параметр  можно  установить  в  nil.
 
 DwFlags  задает  параметры,  влияющие  на  поведение  Internet-  функций.
         Возможно  применение  комбинации  из  следующих  разрешенных  значений:
         INTERNET_FLAG_ASYNC,  INTERNET_FLAG_FROM_CACHE,
         INTERNET_FLAG_OFFLINE.  

Q-470: Как перед скачиванием узнать размер файла?

 GetUrlInfo(HTTP_QUERY_CONTENT_LENGTH,  'http://some.com/some.zip');
 
 function  GetUrlInfo(const  dwInfoLevel:  DWORD;  const  FileURL:  string):  
 string;
 var
     hSession,  hFile:  hInternet;
     dwBuffer:  Pointer;
     dwBufferLen,  dwIndex:  DWORD;
 begin
     Result  :=  '';
     hSession  :=  InternetOpen('STEROID  Download',
                                                       INTERNET_OPEN_TYPE_PRECONFIG,  nil,  nil,  0);
     if  Assigned(hSession)  then  begin
         hFile  :=  InternetOpenURL(hSession,  PChar(FileURL),  nil,  0,
                                                           INTERNET_FLAG_RELOAD,  0);
         dwIndex    :=  0;
         dwBufferLen  :=  20;
         if  HttpQueryInfo(hFile,  dwInfoLevel,  @dwBuffer,  dwBufferLen,  dwIndex)
             then  Result  :=  PChar(@dwBuffer);
         if  Assigned(hFile)  then  InternetCloseHandle(hFile);
         InternetCloseHandle(hsession);
     end;
 end;

Q-480: Можно ли как-нибудь обеспечить стабильную работу на машинах со старыми версиями WinInet?

 Еще  кое-какой  код,  который  может  оказаться  полезным  в  плане
 обеспечения  стабильной  работы  на  машинах  со  старыми  версиями
 wininet.dll  или  вообще  отсутствия  оной.
 
 var
     WinInetDLL:  THandle  =0;
 
     _InternetOpenA:  function(lpszAgent:  PAnsiChar;  dwAccessType:  DWORD;
                                     lpszProxy,  lpszProxyBypass:  PAnsiChar;
                                     dwFlags:  DWORD):  HINTERNET;  stdcall;
 
     _InternetOpenURLA:  function(hInet:  HINTERNET;  lpszUrl:  PAnsiChar;
                                           lpszHeaders:  PAnsiChar;  dwHeadersLength:  DWORD;
                                           dwFlags:  DWORD;  dwContext:  DWORD):  HINTERNET;  stdcall;
 
     _InternetReadFile:  function(hFile:  HINTERNET;  lpBuffer:  Pointer;
                                           dwNumberOfBytesToRead:  DWORD;
                                           var  lpdwNumberOfBytesRead:  DWORD):  BOOL;  stdcall;
 
     _InternetCloseHandle:  function(hInet:  HINTERNET):  BOOL;  stdcall;
 
 
 procedure  InitWinInet;
 var
     OldError:  Longint;
 begin
     OldError  :=  SetErrorMode(SEM_NOOPENFILEERRORBOX);
     try
         if  WinInetDLL  =  0  then  begin
             WinInetDLL  :=  LoadLibrary('wininet.dll');
             if  WinInetDLL  <>  0  then  begin
                 @_InternetOpenA  :=
                                                 GetProcAddress(WinInetDLL,'InternetOpenA');
                 @_InternetOpenURLA  :=  
                                                 GetProcAddress(WinInetDLL,'InternetOpenUrlA');
                 @_InternetReadFile  :=  
                                                 GetProcAddress(WinInetDLL,'InternetReadFile');
                 @_InternetCloseHandle  :=  
                                                 GetProcAddress(WinInetDLL,'InternetCloseHandle');
             end;
         end;
     finally
         SetErrorMode(OldError);
     end;
 end;
 
     ...
     if  WinInetDLL  =  0  then  InitWinInet;
     if  WinInetDLL  <>  0  then  begin
         ...
     end  else  ShowMessageUser('Hе  могу  загрузить  WinInet.dll');
     ...