使用java中的套接字向服务器发送请求

Dan*_*iel 1 java sockets

我正在使用套接字与服务器建立流连接。通过创建套接字,我尝试使用套接字向服务器发送请求。但是无论我使用哪种方法,服务器都不会收到请求。这些是我用来发送请求的方法。

PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(query);
Run Code Online (Sandbox Code Playgroud)

或者另一个是

 out = new ObjectOutputStream(connection.getOutputStream());
 out.writeObject(msg);
 out.flush();
Run Code Online (Sandbox Code Playgroud)

我试图发送的请求是这样的:

String query = String.format("cmd=%s&version=%s", "handshake", "1.0");
Run Code Online (Sandbox Code Playgroud)

我知道使用 Httpconnection 发送此查询要容易得多,但这是必须完成的方式。所以请帮我解决这个问题。这是 httpconnection 命令

 String charset = "UTF-8";
 String query = String.format("cmd=%s&version=%s", "handshake", "1.0");
 String charset = "UTF-8";
 URL url = new URL("serveraddress:8080");           
 URLConnection conn = url.openConnection();         
 conn.setDoOutput(true);            
 conn.connect();            
 OutputStream output = conn.getOutputStream();              
 output.write(command.getBytes(charset));                                       

 InputStreamReader content = new InputStreamReader(conn.getInputStream());                              
 String result ="";
 int c = content.read();
 while (c != -1) {
    result = result + ((char) c);  
        c = content.read();
} 
 Log.v(logTag, "Received: [" + result + "]");
Run Code Online (Sandbox Code Playgroud)

这就是我在套接字中所做的,但不起作用

 URL url = new URL("serveraddress:8080");               
 String server_name = url.getHost();
 int port = url.getPort();
 Socket socket = new Socket(server_name, port);                         

 String query = "post /swarm HTTP/1.1\nHost: serveraddress\n" +
 "content-length: 27\nkeep-alive: 300\nconnection: keep-alive\n\n" +
 "cmd=handshake&version=1.0\n"; 

 PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
 out.println(query);
Run Code Online (Sandbox Code Playgroud)

根据服务器日志,套接字连接在没有收到任何请求的情况下打开和关闭

Jid*_*ddo 5

您提到的三种方法(PrintWriter、ObjectOutputStream 和 HTTPConnection)都会导致将某些内容发送到服务器,但实际发送的内容在各种方法之间会有很大差异。

首先,Java ObjectOutputStream类将对您写入的对象以及这些对象所属的类的信息进行编码,尤其是类名、签名等。这实际上仅适用于您与另一个 Java 应用程序通信时在另一端使用ObjectInputStream来读取它。它尤其不会遵守 HTTP 协议,因此您很可能根本无法将它与任何可以使用 HTTPConnection 的东西一起使用。

使用HttpURLConnection实际上会构造并向您尝试连接的服务器发送完整的(最重要的是有效的)HTTP 请求。例如,如果您要执行以下代码:

URL url = new URL("http://localhost/test?cmd=handshake&version=1.0");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
Run Code Online (Sandbox Code Playgroud)

然后结果将是您的应用程序连接到localhost:80并写入如下内容:(这是一个简化的请求。实际请求中会有额外的标头和信息。)

GET /test?cmd=handshake&version=1.0 HTTP/1.1
Host: localhost
Run Code Online (Sandbox Code Playgroud)

最后,如果您使用的是PrintWriter,那么它实际上会将纯文本发送到服务器。但是,如果服务器是 HTTP 服务器,这很可能是因为您说它响应 HTTP 连接,那么仅发送请求的命令部分是不够的。您还必须发送其余部分,包括GET、HTTP 版本、可能还有一些标头、尾随空行和 CRLF 行结尾。这一切都可以使用 PrintWriter 来完成。

安装一个网络数据包分析器(例如 Wireshark)并使用它来实际查看当您使用 httpconnection 执行连接时发送到服务器的内容,然后尝试通过手动构建请求来模拟它时,这可能是一个好主意。

我还建议阅读有关 HTTP 协议的更多详细信息。一个好的起点可以是Wikipedia 文章

根据 OP 中的新信息进行编辑:

更新后的代码中存在一些小的不一致之处,其中一些我可以假设是复制粘贴错误,另一些我想指出以防万一。

基于 URLConnection 的解决方案不会在任何地方指定“/swarm”资源。添加它不会改变请求是否实际发送,甚至它是否有效,但它可能会影响您是否可以在日志中找到请求。

除了POST使用小写字母编写外,查询字符串总体上看起来很合理。起初我不认为这会有什么不同,但是当通过 Telnet 对 www.google.com 尝试“get”与“GET”时,它似乎确实有所不同。如果 Web 服务器无法将请求识别为请求,那么它将无法处理它,因此它可能不会像您期望的那样显示在日志中。

我建议您实际阅读服务器响应并将其打印到 System.out,以便您查看服务器是否报告了任何特定错误。