![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Web сервер. [D5, Win95/98]
Qwert622 © (2004-01-05 16:06:00)Есть небольшой пример позаимствованный из сети.
Пример представляет собой web-сервер на основе TServerSocket.
Порт - ServerSocket.Port:=80;
Отрабатывает только GET.
=========
procedure TForm1.WWW_SSClientRead(Sender:TObject; Socket:TCustomWinSocket);
var st:string;
begin
try
if Socket.Connected=true then st:=Socket.ReceiveText;
st:=Copy(st,Pos('/',st),Pos(' HTTP/',st)-Pos('/',st));
ExecuteQuery(st,Socket);
Socket.Close;
except
try
if Socket.Connected=true then Socket.Close;
except
Exit;
end;
end;
end;
procedure TForm1.ExecuteQuery(AQuery:string; Socket:TCustomWinSocket);
var FlName,Params:string;
FlStream:TFileStream;
Fl:file of byte;
FlSize:string;
begin
if not Socket.Connected then exit;
AQuery:=trim(AQuery);
Params:='';
FlName:='';
if pos('?',AQuery)>0 then begin
Params:=trim(copy(AQuery,pos('?',AQuery)+1,length(AQuery)));
delete(AQuery,pos('?',AQuery),length(AQuery));
end;
FlName:=trim(AQuery);
if FlName='/' then FlName:=FlName+WWWDefPage;
FlName:=WWWRoot+FlName;
if FileExists(FlName)=true then begin
AssignFile(Fl,FlName); Reset(Fl);
FlSize:=trim(inttostr(FileSize(Fl)));
Closefile(Fl);
Socket.SendText('HTTP/1.0 200 OK'+#$0D+#$0A);
Socket.SendText('Content-Length: '+FlSize+#$0A);
Socket.SendText('Server: WWW_SS'+#$0A);
Socket.SendText(#$0D+#$0A);
FlStream:=TFileStream.Create(FlName,fmOpenRead);
FlStream.Position:=0;
try
Socket.SendStream(FlStream);
finally
Memo1.Lines.Add('Файл передан.');
end;
end
else begin
Socket.SendText('HTTP/1.0 404 Not Found'+#$0D+#$0A);
Socket.SendText('Server: WWW_SS'+#$0A);
Socket.SendText(#$0D+#$0A);
Memo1.Lines.Add('Файл не найден.');
end;
end;
=========
А теперь вопросы по этому примеру:
1. При передачи картинки (jpg, bmp) по запросу штатного виндувсового IE 6.0 часто (но не всегда!?) эксплорер получает только часть картинки. При этом html файлы передаются всегда нормально (целиком).
Почему??? Как лечить???
2. Принципиально не хочет работать если IE соединяется с сетью через прокси-сервер. Т.е TServerSocket - даже не чувствует что к нему подключаются.
Почему??? Как лечить???
Заранее спасибо всем кто ответит. По возможности с примером.
Polevi (2004-01-08 18:00:00) [21]>Qwert622 (08.01.04 17:31) [14]
еще раз повторяю, писать в сокет в асинхронном режиме можно только в событии OnWrite, ты пишешь в OnRead - это неправильно, то что у тебя работает (возможно ) на локальной машине - в сети работать не будет
Verg (2004-01-08 17:56:00) [22]function FileTypeToMimeType(const Ft : string):string;
begin
result:='';
with TRegistry.Create do
try
RootKey:=HKEY_CLASSES_ROOT;
if OpenKey(ExtractFileExt(Ft), false) then
try
Result:=ReadString('Content Type')
except
result:=MimeTypes.Values[ExtractFileExt(Ft)];
end else result:=MimeTypes.Values[ExtractFileExt(Ft)];
finally
Free;
if Result='' then result:='text/plain';
end;
end;
> if FileExists(FlName)=true then begin
> FlStream:=TFileStream.Create(FlName,fmOpenRead);
> Socket.SendText('HTTP/1.0 200 OK'+#$0D+#$0A+
Content-Length: '+IntToStr(FlStream.Size)+#$0D+#$0A+
Server: WWW_SS'+#$0D+#$0A+
'Content-Type: '+FileTypeToMimeType(FlName)+#13#10+
#$0D+#$0A);
> try
> Socket.SendStreamThenDrop(FlStream);
> Memo1.Lines.Add('Передача файла успешно началась...');
> except
> Memo1.Lines.Add('Обшибочка');
> end;
> end
Сокет при этом вручную не закрывать!!!
Qwert622 (2004-01-08 17:31:00) [23]Polevi © (08.01.04 15:36) [13]
Приведенный пример с исправлением [11] работает. Это проверено.
При присоединение IE НЕ через прокси проблемы не возникают;
html-ки с картинками размещенные на таком сервере загружаются корректно.
Для себя первую часть вопроса на данный момент считаю ЗАКРЫТОЙ.
Polevi (2004-01-08 15:36:00) [24]ибо все равно в результате будет вызван winsock.send, который вернет WSAEWOULDBLOCK
Polevi (2004-01-08 15:32:00) [25]Qwert622 (08.01.04 15:14) [11]
приведенный тобой пример с SendBuf тоже не будет работать, не вводи народ в заблуждение
Qwert622 (2004-01-08 15:14:00) [26]Благодарю всех принявших участие в обсуждении.
Ответ на первую часть вопроса такой:
в приведенном примере нужно для передачи файла вместо Socket.SendStream(... использовать Socket.SendBuf(... . Тогда глюк с приемом картинки в IE в рваном виде пропадает.
Пока остается открытой вторая часть вопроса:
Почему при работе IE через прокси вообще не происходит соединения с ServerSocket.
Т.е процедура TForm1.WWW_SSClientConnect не срабатывает при попытке соединения.
Ole (2004-01-06 13:33:00) [27]По поводу неполной картинки - тоже был косяк:
Надо правильно заполнить заголовок HTTP. Указать MIME тип и размер!
Content type
Content length и тп
А в конце каждой строки CRLF а не тока LF
Polevi (2004-01-05 19:26:00) [28]ну ладно, я сегодня добрый
проблема твоя в том, что метод SendStream не отправялет твой поток целиком, ибо не может этого сделать
вот тебе тестовый пример
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp;
type
TForm1 = class(TForm)
cs: TClientSocket;
ss: TServerSocket;
procedure csWrite(Sender: TObject;
Socket: TCustomWinSocket);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
ss.Port:=6666;
ss.Active:=true;
cs.Address:='127.0.0.1';
cs.Port:=6666;
cs.Active:=true;
end;
procedure TForm1.csWrite(Sender: TObject;
Socket: TCustomWinSocket);
var
fs:TFileStream;
begin
fs:=TFileStream.Create('c:\bigfile.exe',fmOpenRead);
if not Socket.SendStream(fs) then
beep;
Caption:=IntToStr(fs.Position);
end;
end.
метод SendStream возвратит управление отправив только часть потока, и вот почему
кусок исходников от Борладна
function TCustomWinSocket.SendStreamPiece: Boolean;
....
AmountSent := send(FSocket, Buffer, AmountInBuf, 0);
if AmountSent = SOCKET_ERROR then
begin
ErrorCode := WSAGetLastError;
if ErrorCode <> WSAEWOULDBLOCK then
begin
Error(Self, eeSend, ErrorCode);
Disconnect(FSocket);
DropStream;
if FAsyncStyles <> [] then Abort;
Break;
end else
begin
FSendStream.Position := StartPos;
Break;
end;
...
end;
вызов winsock ф-ии send для неблокируещего сокета привел к ошибке WSAEWOULDBLOCK, что означает "буфер приемник переполнен, я сообщу тебе когда он будет готов принять следующую порцию данных событием FD_WRITE" и ф-ия SendStream возвратила управление, отправив только часть потока
Qwert622 (2004-01-05 18:35:00) [29]Для FireMan_Alexey.
Я наверное не очень хорошо сформулировал вопрос (вернее 2 вопроса).
1."Сервер" корректно получает получает запрос от IE, корректно обрабатывает его, находит запрашиваемый файл, отправляет его эксплореру (Socket.SendStream(FlStream);), НО эксплорер (кстати и NetVampire) получает только ЧАСТЬ файла.
Как я понимаю это связано с тем что посылаемый сервером поток при передаче может быть (а может и не быть) разорван на несколько частей. И експлореру нужно как то объяснить что эти части нужно сшивать. А вот как - этого я пока и не понял.
2. При работе IE через прокси вообще не происходит соединения с ServerSocket - и это есть отдельный вопрос.
По поводу "if Socket.Connected=true then st:=Socket.ReceiveText;" - да Вы правы. Эта строка не нужна но и помешать работе она не может.
FireMan_Alexey (2004-01-05 18:14:00) [30]Дело в том, что при возникновении Read в буфере может оказаться
и 1 байт, а не строка!
По этому обрабатывать запрос експлорера нужно проверяя
строку на символы #13#10, повторяющиеся 2 раза. Это, как я понял,
отделяет загаловок от последующих данных. Т.к. при посылке дву строк за короткий промежуток времени "Привет", а затем " Мир" сервер получит "Привет Мир" или может "Приве" и "т Мир". Т.е. нет уверенности в том, что ты получил нужные данные!
1) Зачем это!? if Socket.Connected=true then st:=Socket.ReceiveText;
Если возникает Чтение значит сокет существует и он открыт!
2) Еще вопрос, а не проще в неблок режиме?
Polevi (2004-01-05 18:14:00) [31]конкретно почитай хелп на ф-ию WSAAsyncSelect
Polevi (2004-01-05 18:05:00) [32]Удалено модератором
Примечание: Разборки в чате устраиваем ...
Qwert622 (2004-01-05 18:02:00) [33]Удалено модератором
Примечание: Разборки в чате устраиваем ...
Polevi (2004-01-05 17:46:00) [34]чтобы встретить указания надо читать документацию, вот и займись этим
Qwert622 (2004-01-05 17:13:00) [35]1. Для простоты считаем что уверенность есть.
При работе IE не через прокси - в буфере оказывается не рваный запрос. А при работе IE через прокси - в буфере вообще ничего не оказывается поскольку не происходит WWW_SSClientConnect. К серверу никто не присоединяется.
2. То что было послано от сервера к IE посредством SendText - компьютер с експлорером получает. (Это проверялось в NetVempire - он показывает протокол обмена клиент-сервер).
3. Я не встречал указаний на то, что нельзя писать в сокет данные в обработчике ClientRead. Тем более что данные пишутся. Почему-то только не всегда целиком (или не целиком читаются IE ?).
4. Это само собой. А всетаки возвращаясь к вопросу ...
Polevi (2004-01-05 16:43:00) [36]откуда уверенность в том что на момент вызова ReceiveText в буфере гнезда будет находится запрос целиком, а не его чаcть ?
где анализ результата SendText ?
почему ты пишешь в сокет данные в обработчике ClientRead, в нем можно только читать, для записи предназначено событие ClientWrite
тебе нужно почитать про асинхронный режим winsock, иначе ничего у тебя путного не выйдет
или работай в блокирующем режиме