Content


I-1: Ru.Delphi.Internet FAQ

I-2: 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
 Igor  Myslovsky,  2:4625/48
 Denis  V.  Skibin,  2:5075/5.31
 Andrew  Ryazanov,  rash@land.ru

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

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

I-4: О поле Subject

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

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

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

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

 Этот  документ  регулярно  изменяется  в  результате  отслеживания
 происходящего  в    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-7: Рекомендуемые источники информации.

 Прежде  всего,  конечно  же,  книги.  Как  бы  это  странно  ни
 звучало,  но  зайдите  в  книжный  магазин  и  купите  себе  там
 какую-нибудь  книгу,  даже  если  она  уже  у  Вас  есть.  Следует
 сразу  предупредить,  что  специфика  современного  российского
 книгоиздания  такова,  что  существует  довольно  большое
 количество  книг,  не  стоящих  своих  денег.  Вероятно,  Вам
 следует  положиться  на  собственное  чутье  и  тщательно  изучить
 предлагаемую  продукцию.
 
 Список  литературы  на  все  интересующие  темы,  рекомендованный
 к  прочтению,  находится  в  неофициальном  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-8: Что мне нужно, чтобы писать приложения для Internet или использующие Internet для передачи данных?

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

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

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

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

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

Q-11: Я хочу отправлять из моего приложения электронную почту по протоколам 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-12: Мне надо реализовать обмен данными между двумя удаленными машинами (переслать файл).

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

Q-13: Как мне сделать обмен данными (файлами), как в 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-14: А что такое сокет?

 Существует  мировой  стандарт  структуры  протоколов  связи  -
 семиуровневая  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-15: Hужно сканировать порты через сокс-прокси сервер. Как это сделать?

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

Q-16: У меня ни 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-17: Как пе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-18: Хочу получать информацию о дате и времени из Internet.

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

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

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

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

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

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

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

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

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

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

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

Q-24: Я слышал, что 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-25: Как мне отлаживать 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-26: Мое CGI-приложение при обращении к нему ничего не возвращает. Что делать?

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

Q-27: Бардак с кириллицей в параметрах 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-28: Как отправить письмо, с помощью клиента по умолчанию?

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

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

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

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

 Для  отправки  письма  с  помощью  зарегистрированого  клиента
 используется  функция  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-31: Как узнать 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-32: Как по IP определить имя машины ?

 function  GetHostByIP(IPAddr:  String):  String;  //  Полyчение  имени  по  IP
 var
     Error:  DWORD;
     SockAddrIn:  TSockAddrIn;
     HostEnt:  PHostEnt;
     Data:  TWSAData;
 begin
     Result:='Error';
     Error:=WSAStartup($101,  Data);
     if  Error  =  0  then  begin
       SockAddrIn.sin_addr.s_addr:=  inet_addr(PChar(IPAddr));
       HostEnt:=  gethostbyaddr(@SockAddrIn.sin_addr.S_addr,  4,  AF_INET);
       if  HostEnt<>nil  then  Result:=StrPas(Hostent^.h_name);
     end;  //  Error=0
     WSACleanup();
 end;
 

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

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

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

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

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

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

Q-36: Как узнать домен, к которому я в данный момент подключен? Используется 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-37: Как из своей программы вызвать диалог изменения настроек Internet?

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

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

 Следует  подключить  модуль  WinInet.pas,  в  котором  есть  замечательная
 функция  InternetGetConnectedState...
 
 Кстати,  в  этом  модуле  имеются  заголовки  еще  массы  других  полезных
 функций.
 
 Предложение  от  Анатолия  Подгорецкого
 
 The  easiest  way  to  find  out  if  and  how  (proxy,  ras...)  you  are  connected  to  the
 
 Internet,  without  the  overhead  of  installing  components,  is  the  following:
 
 ------------------------>  Snippet
 USES  WinInet;
     ..
 function  InternetConnected:  Boolean;
 {
 INTERNET_CONNECTION_MODEM    =  1;  //  local  system  uses  a  modem  to  
 connect  to  the  Internet.
 INTERNET_CONNECTION_LAN                =  2;  //  local  system  uses  a  local  area  
 network  to  connect  to  the  Internet.
     INTERNET_CONNECTION_PROXY            =  4;  //  local  system  uses  a  proxy  server  to
 connect  to  the  Internet.
     INTERNET_CONNECTION_MODEM_BUSY  =  8;  //  local  system's  modem  is  busy  with  a
 non-Internet  connection.
 }
 VAR
     dwConnectionTypes  :  DWORD;
 BEGIN
     dwConnectionTypes  :=
       INTERNET_CONNECTION_MODEM  +
   INTERNET_CONNECTION_LAN  +
   INTERNET_CONNECTION_PROXY;
     Result  :=  InternetGetConnectedState(@dwConnectionTypes,0);
 END;
 <--------------------  Snippet
 
 dwConnectiontype  holds  the  appropriate  flags  after  the  call.  This  snippet  comes
 from
 http://inner-smile.com/delphit2.htm

Q-39: Могут ли передаваться данные из 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-40: Почему при использовании метода TWebBrowser.Navigate нужно указывать полное имя файла?

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

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

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

Q-42: Как определить свой 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-43: Как с помощью Indy работать с Socks Proxy?

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

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

 www.ritlabs.com

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

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

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

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

Q-47: Как скачать файл, используя 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-48: Как перед скачиванием узнать размер файла?

 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-49: Можно ли как-нибудь обеспечить стабильную работу на машинах со старыми версиями 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');
     ...

Q-50: Как написать ping'ер?

 function  GetHostByIP(IPAddr:  String):  String;  //  Полyчение  имени  по  IP
 var
     Error:  DWORD;
     SockAddrIn:  TSockAddrIn;
     HostEnt:  PHostEnt;
     Data:  TWSAData;
 begin
     Result:='Error';
     Error:=WSAStartup($101,  Data);
     if  Error  =  0  then  begin
       SockAddrIn.sin_addr.s_addr:=  inet_addr(PChar(IPAddr));
       HostEnt:=  gethostbyaddr(@SockAddrIn.sin_addr.S_addr,  4,  AF_INET);
       if  HostEnt<>nil  then  Result:=StrPas(Hostent^.h_name);
     end;  //  Error=0
     WSACleanup();
 end;

Q-51: Как можно узнать имена компьютеpов (или их ip-адpеса), имеющихся в локальной сети?

 procedure  TFormMain.LoadNetResources;
 begin
     with  TreeView.Items  do
     begin
         BeginUpdate;
         Clear;
         Add(nil,  'Any  naou');
         EnumSubResources(TreeView.Items,  Item[0],  nil);
         EndUpdate;
     end;
 end;
 
 procedure  TFormMain.EnumSubResources(Items:  TTreeNodes;  Node:  TTreeNode;
     lpNetResource:  PNetResource);
 const
     MAX_RES  =  16;
 type
     PResources  =  ^TResources;
     TResources  =  array[0..MAX_RES-1]  of  TNetResource;
 var
     hEnum:  THandle;
     Count:  Integer;
     Res:  Integer;
     Resources:  PResources;
     BufferSize:  Integer;
     I:  Integer;
     NewNode:  TTreeNode;
     NewNodeName:  String;
 begin
     Res  :=  WNetOpenEnum(RESOURCE_GLOBALNET,  RESOURCETYPE_ANY,  0,
 lpNetResource,  hEnum);
     if  NO_ERROR  <>  Res  then
         Exit;
     BufferSize  :=  SizeOf(TResources);
     GetMem(Resources,  BufferSize);
     while  True  do
     begin
         Count  :=  MAX_RES;
         Res  :=  WNetEnumResource(hEnum,  Count,  Resources,  BufferSize);
         if  (Res  <>  NO_ERROR)  and  (Res  <>  ERROR_MORE_DATA)  then
             Break;
         for  I  :=  0  to  Count  -  1  do
         begin
             if  Assigned(Resources^[I].lpRemoteName)  then
                 NewNodeName  :=  String(Resources^[I].lpRemoteName)
             else
                 NewNodeName  :=  String(Resources^[I].lpComment);
             NewNode  :=  Items.AddChild(Node,  NewNodeName);
             if  (Resources^[I].dwUsage  and  RESOURCEUSAGE_CONTAINER)  <>  0  then
                 EnumSubResources(Items,  NewNode,  @(Resources^[I]));
         end;
     end;
     FreeMem(Resources);
     WNetCloseEnum(hEnum);
 end;

Q-52: Как узнать MAC адрес компьютера ?

 Как  узнать  MAC  адрес  компьютера  ?