从其它平台迁移而来
对于上节的示例中,比较适合发送小文件,若直接用于发送大文件的话,很容易把服务器的内存资源耗尽。当请求大文件时,可以限制每次发送大文件时使用的内存大小(例如16000 B
)。
-
打开上节的工程
-
修改RtcDataProvider3
的OnCheckRequest
事件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
var
fname: string;
begin
with TRtcDataServer(Sender) do
begin
fname := GetFullFileName(Request.FileName);
if (fname <> '') and (File_Exists(fname)) then
begin
Accept;
Request.Info['fname'] := fname;
Response.ContentLength := File_Size(fname);
WriteHeader;
end;
end;
end;
|
- 修改
RtcDataProvider3
的OnDataReceived
事件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
var
fname: string;
len: cardinal;
begin
with TRtcDataServer(Sender) do
if Request.Complete then
begin
if Response.ContentLength > Response.ContentOut then
begin
fname := Request.Info['fname'];
if File_Size(fname) = Response.ContentLength then
begin
len := Response.ContentLength - Response.ContentOut;
if len > 16000 then
len := 16000;
Write(Read_File(fname, Response.ContentOut, len));
end
else
Disconnect;
end;
end;
end;
|
-
关联RtcDataProvider3
的OnDataSent
事件到OnDataReceived
事件的实现,使两个事件都指向同一段代码
-
编译并运行
-
在data
文件夹下放入一个大文件(例如test.mp3
),访问网址http://localhost/test.mp3
流程分析#
为了更进一步了解整个过程,把RtcHttpServer1
和RtcDataProvider3
的每个事件都记录进日志:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
[22:36:08.272] RtcHttpServer1ListenStart->
[22:36:08.292] RtcDataProvider3ListenStart->
[22:36:26.108] RtcHttpServer1ClientConnect->
[22:36:26.118] RtcHttpServer1Connecting->
[22:36:26.130] RtcHttpServer1Connect->
[22:36:26.160] RtcHttpServer1DataIn->
[22:36:26.164] RtcDataProvider3CheckRequest->请求文件:F:\RTC\bin\data\test.ppt [12521984 B]
[22:36:26.169] RtcHttpServer1RequestAccepted->
[22:36:26.175] RtcDataProvider3DataOut->
[22:36:26.178] RtcHttpServer1DataOut->
[22:36:26.257] RtcHttpServer1PeekRequest->
[22:36:26.262] RtcDataProvider3DataReceived->剩余:12521984 B
[22:36:26.276] RtcDataProvider3DataOut->
[22:36:26.281] RtcHttpServer1DataOut->
[22:36:26.286] RtcDataProvider3DataSent->剩余:12505984 B
[22:36:26.301] RtcDataProvider3DataOut->
[22:36:26.311] RtcHttpServer1DataOut->
[22:36:26.316] RtcDataProvider3ReadyToSend->
[22:36:26.323] RtcDataProvider3DataSent->剩余:12489984 B
[22:36:26.338] RtcDataProvider3DataOut->
[22:36:26.345] RtcHttpServer1DataOut->
...
[22:36:50.488] RtcDataProvider3ReadyToSend->
[22:36:50.494] RtcDataProvider3DataSent->剩余:9984 B
[22:36:50.507] RtcDataProvider3DataOut->
[22:36:50.515] RtcHttpServer1DataOut->
[22:36:50.522] RtcDataProvider3ReadyToSend->
[22:36:50.528] RtcDataProvider3DataSent->
[22:36:50.534] RtcDataProvider3ResponseDone->
[22:36:50.540] RtcHttpServer1ResponseDone->
[22:38:45.919] RtcHttpServer1Disconnecting->
[22:38:45.950] RtcHttpServer1Disconnect->
[22:38:45.968] RtcHttpServer1ClientDisconnect->
[22:46:04.945] RtcDataProvider1ListenStop->
[22:46:04.955] RtcHttpServer1ListenStop->
|
-
服务端启动,RtcHttpServer1
开始监听,RtcDataProvider3
随着也开始监听
-
在浏览器中请求文件,RtcHttpServer1
收到客户端的连接,RtcHttpServer1
开始连接,连接成功,RtcHttpServer1
收到数据(请求),RtcDataProvider3
也收到请求
-
RtcDataProvider3
在OnCheckRequest
事件中检查请求,文件存在,接受请求
-
RtcHttpServer1
确定请求被接受,RtcDataProvider3
把文件名写入请求信息Request.Info['fname']
中备用,把文件大小写入到响应长度Response.ContentLength
里,然后把响应头发送出去(实际是发送给RtcHttpServer1
,然后RtcHttpServer1
把响应最终发出)
-
RtcHttpServer1
Peek请求,RtcDataProvider3
触发OnDataReceived
事件
-
RtcDataProvider3
接收到完整的请求后才进行处理,文件未发现修改(大小未改变)且文件超过16000 B
,只发送16000 B
(发给RtcHttpServer1
,RtcHttpServer1
再转发)
-
RtcDataProvider3
数据发出,触发OnDataSent
事件,事件处理中发现文件未发完,准备数据继续发送(依然是只发送16000 B
,由RtcHttpServer1
转发),发送后又触发OnDataSent
事件……
-
直到文件数据全部发送完,RtcDataProvider3
完成响应,RtcHttpServer1
也完成响应
-
浏览器关闭,RtcHttpServer1
开始断开连接,连接断开
-
关闭服务端,RtcDataProvider3
停止监听,RtcHttpServer1
也停止监听