从其它平台迁移而来


对于上节的示例中,比较适合发送小文件,若直接用于发送大文件的话,很容易把服务器的内存资源耗尽。当请求大文件时,可以限制每次发送大文件时使用的内存大小(例如16000 B)。

  1. 打开上节的工程

  2. 修改RtcDataProvider3OnCheckRequest事件:

 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;
  1. 修改RtcDataProvider3OnDataReceived事件:
 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;
  1. 关联RtcDataProvider3OnDataSent事件到OnDataReceived事件的实现,使两个事件都指向同一段代码

  2. 编译并运行

  3. data文件夹下放入一个大文件(例如test.mp3),访问网址http://localhost/test.mp3

流程分析

为了更进一步了解整个过程,把RtcHttpServer1RtcDataProvider3的每个事件都记录进日志:

 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->
  1. 服务端启动,RtcHttpServer1开始监听,RtcDataProvider3随着也开始监听

  2. 在浏览器中请求文件,RtcHttpServer1收到客户端的连接,RtcHttpServer1开始连接,连接成功,RtcHttpServer1收到数据(请求),RtcDataProvider3也收到请求

  3. RtcDataProvider3OnCheckRequest事件中检查请求,文件存在,接受请求

  4. RtcHttpServer1确定请求被接受,RtcDataProvider3把文件名写入请求信息Request.Info['fname']中备用,把文件大小写入到响应长度Response.ContentLength里,然后把响应头发送出去(实际是发送给RtcHttpServer1,然后RtcHttpServer1把响应最终发出)

  5. RtcHttpServer1Peek请求,RtcDataProvider3触发OnDataReceived事件

  6. RtcDataProvider3接收到完整的请求后才进行处理,文件未发现修改(大小未改变)且文件超过16000 B,只发送16000 B(发给RtcHttpServer1RtcHttpServer1再转发)

  7. RtcDataProvider3数据发出,触发OnDataSent事件,事件处理中发现文件未发完,准备数据继续发送(依然是只发送16000 B,由RtcHttpServer1转发),发送后又触发OnDataSent事件……

  8. 直到文件数据全部发送完,RtcDataProvider3完成响应,RtcHttpServer1也完成响应

  9. 浏览器关闭,RtcHttpServer1开始断开连接,连接断开

  10. 关闭服务端,RtcDataProvider3停止监听,RtcHttpServer1也停止监听