频道分类

Indy TIdTCPClient 的一个用法上要留意的问题,以及 HTTP

作者:admin 来源: 日期:2019/9/20 9:28:17 人气: 标签:TIdTCPClient

 
Delphi 10.3 社区版

测试用 TIdTCPClient 去连接一个 HTTP 服务器,自己写 HTTP 请求,发现一个问题。

 

大致步骤如下:

1. 首先,用 TCP 客户端,连接一个 HTTP 服务器;

2. 向服务器发送 HTTP 请求字符串;

3. 从服务器读返回值;

向服务器发送字符串的方法是:

IdTCPClient1.IOHandler.Write(IB1);   //这里的 IB1 是 TIdBytes;

读返回值的方法是:

IdTCPClient1.IOHandler.ReadBytes(IB2, -1); // IB2 是 TIdBytes;  这里的 -1 是要读的字节数。

如果把要读的字节数,设置为一个正数,比如 100,同时设置超时:IdTCPClient1.IOHandler.ReadTimeout := 50;

假设服务器返回的字节数只有 80 则读会超时,但是,超时后,收到的 IB2 是空的!原本以为它会返回 80个字节的内容呢。

因此,如果你不知道要读多少字节,这里必须用 -1,然后超时后,获得的 IB2 的字节数就是服务器返回的字节数。

TIdTCPClient 的这个特性,不知道是不是一个 BUG,但显然不符合编程的直觉。

看 TIdIOHandler.ReadBytes 这个函数的源代码,似乎是读够了数据就退出,退出读以后才把读到的字节拷贝到这个函数的输出变量里面。没读够超时,可能超时引发的异常导致了没拷贝进去。

 

另外,HTTP 协议:

用 TCP 连上服务器以后,需要发一个 HTTP 头给服务器,才能获得服务器的响应。(服务器是 Indy Web Server)。

HTTP 头实际上是几行字符串,字符串之间用回车换行分隔。最后还要加上一个回车换行(空行)作为结束。

构成 HTTP 头的代码如下,这里的 SL 是 TStringList:

SL := TStringList.Create;
  try
    SL.Add('GET / HTTP/1.1');
    SL.Add('Host: 127.0.0.1:8080');
    SL.Add('Connection: keep-alive');
    SL.Add('Upgrade-Insecure-Requests: 1');
    SL.Add('User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36');
    SL.Add('Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8');
    SL.Add('Accept-Encoding: gzip, deflate');
    SL.Add('Accept-Language: zh-CN,zh;q=0.9');
    SL.Add('');
 
    S1 := SL.Text;
  finally
    SL.Free;
  end;
上述 http 头,如果只有第一行,拿不到服务器的返回。

测试 www.qq.com 的服务器,上述 HTTP 头,如果只有第一行,也能获得服务器的返回字符串,只不过这个字符串是: 404 not found 等等提示。
————————————————

原文链接:https://blog.csdn.net/pcplayer/article/details/89345192