那是行不通的。Sinatra 的服务器理解并使用一种称为http 协议的语言,因此发送字符串:
"This is a text please work"
通过套接字连接到 Sinatra 应用程序是一种绝望的祈祷。
协议是一组规则,指定客户端和服务器如何相互交谈——然后每一方都可以准确地理解对方在说什么。对于 http 协议,客户端发送称为 的内容a request
,而服务器则使用称为 的内容进行回复a response
。请求和响应必须根据 http 协议指定的规则精确地格式化。请求的血腥细节在这里:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html
所以你的java程序需要发送a request
到Sinatra的服务器,它只是一个以精确方式格式化的字符串。下面是一个简单的 GET 请求:
GET /path/to/page HTTP/1.1
Host: localhost:4567
如果要对页面发出 GET 请求:
http://localhost:4567/page1
(即打西纳特拉路线get '/page1'
)
...然后对该页面的简单 GET 请求将如下所示:
GET /page1 HTTP/1.1
Host: localhost:4567
此外,无论您使用什么操作系统,都必须以“\r\n”结束 http 请求中的每一行。这两个字符是 http 协议的一部分。此外,在最后一个标题之后必须有一个由另一个“\r\n”表示的空行,如下所示:
GET /page1 HTTP/1.1\r\nHost: localhost:4567\r\n\r\n
这是java:
import java.io.*;
import java.net.*;
public class Sinatra {
private static void contactServer() {
try {
Socket sock = new Socket("localhost", 4567);
OutputStream os = sock.getOutputStream();
PrintWriter writer = new PrintWriter(os);
String[] text = {
"GET /page1 HTTP/1.1",
"Host: localhost:4567",
};
String request = "";
for(int i=0; i < text.length; ++i) {
request += text[i] + "\r\n";
}
request += "\r\n";
System.out.println(request);
writer.write(request);
writer.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Sinatra.contactServer();
}
}
注意:前几次我运行该 java 程序时,服务器(我开始使用$ ruby myapp.rb
)抛出以下错误:
[2013-08-19 20:10:11] ERROR Errno::ECONNRESET: Connection reset by peer
/Users/7stud/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/httpserver.rb:80:in `eof?'
/Users/7stud/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/httpserver.rb:80:in `run'
/Users/7stud/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'
但是当我再运行几次 java 程序时,服务器最终表现良好。我不知道是什么导致了这个错误。当我在 FireFox 中输入 url 时,服务器从未抛出该错误。所以我用 Firebug 来查看 Firefox 发送的请求;然后我在java程序中使用了所有相同的请求头,但服务器仍然抛出了那个错误。
编辑:我可以通过在关闭套接字之前让 java 程序休眠 1 秒来消除服务器错误。当您显式关闭套接字或程序结束时,套接字将关闭。没有睡眠,我认为套接字在服务器仍在处理请求时关闭。因为浏览器保持套接字打开,所以浏览器永远不会导致服务器抛出该错误。
ruby 客户端也会发生相同的服务器错误:
require 'socket'
port = 4567
host = 'localhost'
s = TCPSocket.new host, port
req = [
"GET /page1 HTTP/1.1",
"Host: localhost:4567",
"Accept: */*",
]
req = req.join("\r\n") << ("\r\n" * 2)
print req
s.write req
s.flush
#sleep(1)
s.close
修复方法是一样的。唯一烦人的细节是为什么curl
unix 命令不会导致服务器抛出该错误:
$ curl -v http://localhost:4567/page1
* About to connect() to localhost port 4567 (#0)
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 4567 (#0)
> GET /page1 HTTP/1.1
> User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8r zlib/1.2.3
> Host: localhost:4567
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html;charset=utf-8
< Content-Length: 0
< X-Xss-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-04-20)
< Date: Tue, 20 Aug 2013 04:59:16 GMT
< Connection: Keep-Alive
<
* Connection #0 to host localhost left intact
* Closing connection #0
使用 -v 选项,curl 打印出请求和响应。使用 curl 发出请求,我从未见过服务器抛出该错误。我想知道 curl 是否也会睡觉?