0

我能够将数据发送到 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();
    }

}
4

1 回答 1

0

那是行不通的。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

修复方法是一样的。唯一烦人的细节是为什么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 发出请求,我从未见过服务器抛出该错误。我想知道 curl 是否也会睡觉?

于 2013-08-20T01:56:23.290 回答