在Sinatra服务器上接收数据



我可以将数据发送到sinatra服务器(字符串),但我不确定如何在sinatra代码中实际接收数据。有人能帮忙吗?

Java客户端(我用来发送数据)代码:

private static void contactServer() {
    try {
        String text = "This is a text please work";
        Socket sock = new Socket("localhost", 4567);
        OutputStream os = sock.getOutputStream();
        URL url = new URL("http://localhost:4567/hello");
        PrintWriter writer = new PrintWriter(os);
        writer.flush();
        writer.write(text);
        url.openStream();
        System.out.println("done");
        String strTemp = "";
        /*while(null != (strTemp = br.readLine())){
            System.out.println(strTemp);
        }*/
    } catch (Exception e) {
        e.printStackTrace();
    }
}

这行不通。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

(即击中Sinatra路线get '/page1'

则该页面的一个简单GET请求将如下所示:

GET /page1 HTTP/1.1
Host: localhost:4567

此外,无论使用何种操作系统,http请求中的每一行都必须以"\r\n"结尾。这两个字符是http协议的一部分。此外,在最后一个标头之后,必须有一个空行,由另一个"\r\n"表示,如下所示:

GET /page1 HTTP/1.1rnHost: localhost:4567rnrn

这是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] + "rn";
            }
            request += "rn";
            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("rn") << ("rn" * 2)
print req
s.write req
s.flush
#sleep(1)
s.close

解决方法也是一样的。唯一琐碎的细节是为什么curlunix命令没有导致服务器抛出错误:

$ 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发出请求,我从未见过服务器抛出那个错误。我想知道卷曲是否也能睡觉?

最新更新