Текущим ведущим 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
Пожалуйста, воздержитесь от задавания вопросов в конференции
RU.DELPHI.INTERNET, до того, как прочтете этот документ, правила
конференции, ознакомитесь со списком рекомендованной литературы
и проведете самостоятельные исследования вопроса. Это поможет
всем нам сохранить на должном высоком уровне соотношение полезной
и бесполезной информации и разгрузить конференции от бесполезного трафика.
Правилами иерархии, в частности, регламентируется содержание
поля Subject ваших писем. Дело в том, что довольно большое
количество "потенциально полезных вам индивидумов" читают эхи
методом "по сабджектам", сознательно не тратя время на письма
под заголовком "Help!", "Проблема" или "Вопрос чайника". В данном
случае использование комбинации клавиш Shift-1 лишь усугубляет
ваше положение. Подумайте об этом.
Не указание же заголовка вообще может вызвать законный вопрос
"ТЫ МЕНЯ УВАЖАЕШЬ", так здесь явное неуважение к читателям
конференции, не хватило даже сил на написание заголовка, то
какое право на получение ответа, лень написать заголовок, так
остальным будет лень отвечать.
* обсуждение вопросов, относящихся к базам данных - существует
конференция RU.DELPHI.DB.
* обсуждение вопросов, относящихся к отчетам - существует
конференция RU.DELPHI.REPORTS.
* обсуждение общих программирования на Delphi - существует
родоначальная конференция RU.DELPHI.
* обсуждение вопросов вида "А что такое Delphi?", "Что такое
Интернет?".Существуют конференции RU.DELPHI.CHAINIK и
RU.INTERNET.CHAINIK.
! К сожалению, мотивация типа "мой аплинк/провайдер не получает
эту эху/ньюсгруппу" в данном случае не принимается, потому что
за продолжительное время, прошедшее с момента создания этих
конференций, следовало бы подумать в первую очередь о себе и
создать для себя необходимое количество каналов поступления
информации.
* обсуждение Вашей совершенно новой и безумно свежей идеи о
том, что эху пора разделить на две/три/больше частей, потому что
читать ее нет никаких сил. Вы даже не в первой сотне придумавших
и успешно высказавших сие. От себя могу посоветовать пользоваться
хорошими программами для чтения эхо-конференций.
* обсуждение тем, не связанных с програмированием на Delphi:
алгоритмы, общие вопросы программирования под Win32, общие
организационные вопросы, связанные с разработкой программного
обеспечения, etc.
* общая неспособность получать информацию из окружающей
реальности также не приветствуется. Прочтите книгу об эффективной
коммуникации и должном отношении ко всему.
Этот документ регулярно изменяется в результате отслеживания
происходящего в 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: подумайте,
нужны ли вам непрерывные усилия по синхронизации?
Если же вы вынуждены использовать этот документ на сайте,
для того, чтобы создать его содержимое, подумайте, нужен
ли вообще ваш сайт?
Остерегайтесь подделок.
Прежде всего, конечно же, книги. Как бы это странно ни
звучало, но зайдите в книжный магазин и купите себе там
какую-нибудь книгу, даже если она уже у Вас есть. Следует
сразу предупредить, что специфика современного российского
книгоиздания такова, что существует довольно большое
количество книг, не стоящих своих денег. Вероятно, Вам
следует положиться на собственное чутье и тщательно изучить
предлагаемую продукцию.
Список литературы на все интересующие темы, рекомендованный
к прочтению, находится в неофициальном 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 над всеми
прочими средствами разработки.
Прежде всего, Вам нужно иметь хотя бы небольшое представление о самой Internet.
Также, Вам нужна Delphi Enterprise, которая содержит все необходимые компоненты и исходники.
Также, для отладки приложений, Вам может понадобится
установить на своем компьютере Internet-сервер. Hаиболее
популярный сервер для *NIX - Apache, имеется также и в
реализации для Windows. Я использую Xitami Server, который
можно бесплатно загрузить на http://www.imatrix.com.
Существует Active-X компонент TWebBrowser - это тот же самый, что используется в MS IE.
Компонент из Netscape Navigator также можно поместить на форму, подробности на http://www.chami.com/tips/delphi/103096D.html
Еще на http://www.pbear.com лежат THTMLViewer и TFrameViewer.
Для этих целей предназначены компоненты TNMFTP, TNMHTTP.
См. также Q46, Q47
DK: Можно также посмотреть в сторону компонент TServerSocket, TClientSocket
и документов RFC2616 (HTTP1.1), RFC1945 (HTTP1.0), RFC765 (FTP)
В 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;
Удобнее всего будет сделать это при помощи сокетов.
В Delphi есть компоненты TClientSocket и TServerSocket, реализующие,
соответственно, клиентский и серверный сокеты. Также, Вы можете использовать
функции API WinSock напрямую - их заголовки находятся в файле winsock.pas.
Однако, на мой взгляд, использование компонентов намного удобнее.
Также можно использовать входящие в поставку Delphi Enterprise компоненты
фирмы NetMasters - это TNMMsgServ и TNMMsg (серверная и клиентская части;
компоненты предназначены для обмена текстовыми сообщениями), TNMStrmServ и
TNMStrm (серверная и клиентская части; компоненты предназначены для обмена
потоками данных), а также TNMUDP, компонент, реализующий протокол UDP (User
Datagrem Protocol, см. также RFC768).
Посмотри спецификацию протокола на
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
Существует мировой стандарт структуры протоколов связи -
семиуровневая 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
Описание протокола SOCKS5 см. в RFC1928: http://www.faqs.org/rfcs/rfc1928.html
Хотя проще запустить уже готовый сканер портов из-под SocksCap или e-Border Client (www.socks.nec.com)
Вопрос: У меня ни 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.
На форме 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;
Вам помогут компоненты TNMDayTime и TNMTime, которые (согласно RFC867 и RFC868
соответственно) и предназначены для этих целей.
Обработать событие OnFailure.
Компонент TNMUUProcessor станет Вашим хорошим помощником.
Если Вам не хочется использовать компоненты от NetMasters, попробуйте
Indy. Информацию о данном наборе компонент можно найти в этом FAQ.
Но! При получении писем (атачей) в кoдировке UUE компоненты из
библиотеки Indy работают не очень корректно. На http://www.rtfm.be/fpiette
можно найти нужный файл pop3cli.zip.
DK: Можно также почитать о MIME в RFCs 2045-2049
Попробуйте набор компонент Internet Direct - Indy.
Взять его можно на http://www.nevrona.com/indy
В подкаталоге DEMOS\INTERNET\CHAT есть пример чата.
Вопрос: Почему не работает следующий код?
begin
ClietnSocket1.Open;
if ClietnSocket1.Socket.Connected then
ClietnSocket1.Socket.SendText('Hello');
{..}
end;
Выдает - ассинхронная ошибка.
Вы работаете в ассинхронном режиме. Следует использовать соответсвующие
события.
Да, действительно, 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'е.
Во-первых, Вам необходим установленный WEB-сервер.
Для Stand-Alone CGI приложений достаточно любого сервера. Я
использую Xitami server. ISAPI/NSAPI Dll поддерживаются всеми
серверами от Microsoft, Netscape Server 2.0, а также сервером Apache.
Во-вторых, это зависит от того, что именно делает Ваша
программа. Если она должна предлагать пользователю
заполнить некую форму, то Вам нужно создать html-файл,
в котором эта форма была бы описана. Описывается форма тэгом