【问题标题】:Where is the error in my post tidtcpclient?我的帖子 tidtcpclient 中的错误在哪里?
【发布时间】:2025-12-18 01:15:02
【问题描述】:

我收到一个错误的请求,我的代码有什么问题

procedure TForm1.Button1Click(Sender: TObject);
begin
  TCPClient1.Host :='aavtrain.com';
  TCPClient1.Port := 80;
  TCPClient1.ConnectTimeout := 10000;
  TCPClient1.OnConnected := TCPClient1Connected;
  TCPClient1.ReadTimeout := 5000;
  TCPClient1.Connect;
end;

procedure TForm1.TCPClient1Connected(Sender: TObject);
var
  s: string;
begin
  //
  TCPClient1.Socket.WriteLn('POST HTTP/1.1');
  TCPClient1.Socket.WriteLn(sLineBreak);
  IdTCPClient1.Socket.WriteLn('http://aavtrain.comindex.asp');
  IdTCPClient1.Socket.WriteLn(sLineBreak);
  TCPClient1.Socket.WriteLn('user_name=binary');
  TCPClient1.Socket.WriteLn('&password=12345');
  TCPClient1.Socket.WriteLn('&Submit=Submit');
  TCPClient1.Socket.WriteLn('&login=true');
  TCPClient1.Socket.WriteLn(sLineBreak);
  repeat
    s := TCPClient1.Socket.ReadLn('');
    Memo1.Lines.Add(s);
  until s.Contains('try again');
  TCPClient1.Disconnect;
end;

【问题讨论】:

  • 如果我是你,我会使用 TIdHTTPinstance,因为它内置了 post 方法...
  • 请提供minimal reproducible example。为什么在您的代码中使用TCPClient1IdTCPClient1?请永远不要显示假代码。
  • 我想了解一下,我可以使用 idhttp 和 tnethttpclient 和 succès,但我想看看 van 是如何使用 idtcpclient 完成的

标签: sockets delphi post connection tcpclient


【解决方案1】:

您的 HTTP 消息完全格式错误,每一行您发送到服务器的都是错误的。


HTTP 消息由三部分组成 - 单个请求/响应行,紧随其后的是标头,然后是正文。标头和正文由单个CRLF CRLF 序列分隔,但您在POST 请求行之后发送CRLF CRLF CRLF 序列。事实上,一般来说,您发送的换行符太多了。

POST 行本身缺少所请求资源的路径。

您根本没有发送任何 HTTP 标头。您正在请求 HTTP 1.1,它需要 Host 标头。而且您不会发送 Content-Type 标头以便服务器知道您要发布什么样的数据,或者发送 Content-Length 标头以便服务器知道您要发布多少数据。

消息体本身也存在格式错误。您需要将网络表单值作为单行发送,而不是作为每个值的单独行发送。

试试这个:

procedure TForm1.Button1Click(Sender: TObject);
var
  PostData, Response: string;
  Enc: IIdTextEncoding;
begin
  PostData := 'user_name=binary&password=12345&Submit=Submit&login=true';
  Enc := IndyTextEncoding_UTF8;
  //
  TCPClient1.Host := 'aavtrain.com';
  TCPClient1.Port := 80;
  TCPClient1.ConnectTimeout := 10000;
  TCPClient1.ReadTimeout := 5000;
  TCPClient1.Connect;
  try
    TCPClient1.Socket.WriteLn('POST /index.asp HTTP/1.1');
    TCPClient1.Socket.WriteLn('Host: aavtrain.com');
    TCPClient1.Socket.WriteLn('Content-Type: application/x-www-form-urlencoded; charset=utf-8');
    TCPClient1.Socket.WriteLn('Content-Length: ' + IntToStr(Enc.GetByteCount(PostData)));
    TCPClient1.Socket.WriteLn('Connection: close');
    TCPClient1.Socket.WriteLn;
    TCPClient1.Socket.Write(PostData, Enc);

    // the following is NOT the right way to read
    // an HTTP response. This is just an example.
    // I'll leave it as an exercise for you to
    // research and figure out the proper way.
    // I've posted pseudo code for this on
    // * many times before...
    Response := TCPClient1.Socket.AllData;
  finally
    TCPClient1.Disconnect;
  end;
  Memo1.Text := Response;
end;

请阅读RFC 2616 和相关的 RFC,以及关于 HTML 网络表单提交的 W3C 规范(请参阅 HTML 4.01HTML5),因为很明显您不了解 HTTP 的实际工作原理。从头开始实现一切并非易事,因为它是一个非常复杂且涉及的协议。

【讨论】:

    最近更新 更多