【问题标题】:Java: Simple http GET request using TCP socketsJava:使用 TCP 套接字的简单 http GET 请求
【发布时间】:2015-10-08 12:30:31
【问题描述】:

我在本地托管一个简单的 PHP 回显服务器。 我正在尝试用 Java 向服务器发送消息,并使用 GET 请求打印响应,但收到“格式错误的 HTTP 请求”错误。谁能告诉我如何正确格式化 GET 请求?

//客户端代码:

import java.io.*;
import java.net.*;

public class TCPclient {

    public static void main(String argv[]) throws Exception {
    String sentence, modifiedSentence;
    BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
    Socket clientSocket = new Socket("localhost", 8000);  
    DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());

    BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            sentence = inFromUser.readLine();

            outToServer.writeBytes(sentence + "\n");
            outToServer.writeChars("GET /echo.php HTTP/1.1" +"\n"); 


            modifiedSentence = inFromServer.readLine();
            System.out.println("FROM SERVER: " + modifiedSentence);
            inFromServer.close();
            outToServer.close();
            inFromUser.close();
            clientSocket.close();
            }

}

//PHP Server code:

<?php

/* Simple php echo page 
*/

//      ini_set('display_errors', 'On');
//      error_reporting(E_ALL | E_STRICT);
      if(isset($_GET['source'])) {
        if ($_GET['source'] == "raw")
           echo file_get_contents(basename($_SERVER['PHP_SELF']));
        else
           echo "<pre>" . htmlspecialchars(file_get_contents(basename($_SERVER['PHP_SELF']))) . "</pre>";
      } else if (isset($_GET['message'])){
        echo strtoupper( htmlspecialchars($_GET['message'])) . '\n';
      } else {
?>
      <html>
        <head>
          <title>Error: No input message</title>
        </head>
        <body>
          <h1> No message</h1>
          <p>Echo server called without sending parameter</p>
        </body>
      </html>
<?php
      }
?>

【问题讨论】:

  • 你试过 "\n\n" 吗?哦等等 - 你必须把用户数据写成一些参数。
  • 现在尝试并得到相同的错误消息。

标签: java sockets tcp


【解决方案1】:

http 服务器可以理解 GET、POST、PUT、DELETE 等词。所以这里有一个问题:

        outToServer.writeBytes(sentence + "\n");
        outToServer.writeChars("GET /echo.php HTTP/1.1" +"\n"); 

那里的第一条语句告诉http服务器它不理解的东西:句子。注释掉该行,您的请求就会生效,您会收到回复。

我猜你想将句子作为参数发布到 echo 服务。你可以把它放在查询字符串中:

        outToServer.writeChars("GET /echo.php?message=" + sentence + " HTTP/1.0\n\n"); 

我还更改了 HTTP 版本并附加了一个额外的 \n,正如 Steffen Ullrich 的评论所指出的:

您还必须添加空行来标记标题的结尾。并且行尾必须是 \r\n 而不是 \n。而且你最好做一个 HTTP/1.0 请求而不是 HTTP/1.1,因为你的代码既不能处理 HTTP keep-alive 也不能处理 HTTP 分块编码

但是,这还不够。您还需要对一些字符进行编码,例如空格。正如@zapl 在评论中指出的那样,get 请求中的 URL 必须经过编码。

我还建议先使用简单的 telnet 测试您的 echo 服务:

telnet localhost 8000

在那里,您可以输入您的消息“GET /echo.php?message=something”并验证它是否有效。一旦你找到了符合预期的东西,你就可以相应地更新 Java 代码。

【讨论】:

  • 我会在url encode sentence 上贴在request line 之前
  • 谢谢,你说得对,我忘了说。现在修好了。 (我稍后会添加你的链接,我现在在打电话,很难)
  • 此外,客户端必须按照w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.23 在请求中包含 Host 标头 - 一些服务器可能会接受缺少 Host 标头的请求,但有些服务器会拒绝此类请求。
  • 也必须是一个空行来标记标题的结尾。并且行尾必须是 \r\n 而不是 \n。最好做一个 HTTP/1.0 请求而不是 HTTP/1.1,因为代码既不能处理 HTTP keep-alive 也不能处理 HTTP 分块编码。
  • 谢谢你们,嵌入我的回答中
猜你喜欢
  • 1970-01-01
  • 2015-12-29
  • 1970-01-01
  • 1970-01-01
  • 2021-09-14
  • 2016-03-03
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多