Java - 通过浏览器/URL 连接到 ServerSocket

Posted

技术标签:

【中文标题】Java - 通过浏览器/URL 连接到 ServerSocket【英文标题】:Java - connection to ServerSocket via browser/URL 【发布时间】:2011-10-07 07:00:07 【问题描述】:

我正在编写一个软件,我受到无法使用套接字连接到使用 ServerSocket 的 java 应用程序的限制。

我想我会尝试使用 URL 连接,因为可以定义要连接的端口

例如:

127.0.0.1:62666

我让我的服务器应用程序监听连接并将输入输出到 jTextArea。通过浏览器连接服务器(127.0.0.1:62666)时,输出:

GET / HTTP/1.1
GET /favicon.ico HTTP/1.1

我有另一个应用程序通过 URL 连接连接到 ServerSocket:

try
        URL url = new URL("http://127.0.0.1:62666");
        URLConnection connection = url.openConnection();
        connection.setDoOutput(true);
        connection.connect();
        PrintWriter writer = new PrintWriter(connection.getOutputStream());
        writer.print("Hello");
        System.out.println("should have worked");
        writer.flush();
        writer.close();
    catch(IOException e)
        e.printStackTrace();
    

它打印出“应该可以工作”的消息仅供参考,但它从不向服务器的 jTextArea 写入任何内容。服务器应用程序的代码如下所示:

try

        ServerSocket serverSock = new ServerSocket(62666);

        while(doRun)
            Socket sock = serverSock.accept();
            BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
            PrintWriter writer = new PrintWriter(sock.getOutputStream());

            InfoReader.gui.writeToTextArea(reader.readLine() + " From IP: " + sock.getInetAddress() + "\n");
            writer.println("Testing123");

            writer.close();

            reader.close();

        
    catch(IOException e)
        e.printStackTrace();
    

注意:通过浏览器连接时会显示文本“Testing123”。

所以我想知道如何以我尝试的方式执行此操作,或者可能读取访问 ServerSocket 的 URL,因此我可以在传递参数(在 URL 中)的同时通过 URL 访问它。

希望这是有道理的:)

谢谢, 迈克。

【问题讨论】:

如果你不被允许使用套接字连接......你意识到每个 TCP 连接,包括 URLConnection,都使用一个套接字,对吧? 服务器收到消息了吗? @ryan:我意识到这一点。很难解释。短篇小说:不允许自己直接实例化 Socket 对象。 @john:不,不是。似乎每当我运行应该连接到它的应用程序时,服务器就会“卡住”。每当我尝试通过浏览器连接到 ServerSocket 之后时,它都会继续尝试连接。 迈克,你有没有找到解决办法?我很想知道你发现了什么或选择做什么。 我从未找到使用 URL 的方法。对于我正在做的事情,目前还不允许我实例化套接字对象,所以我几乎没有足够的能力......感谢您的兴趣:) 【参考方案1】:

有一个很好的example:

public class SimpleHTTPServer 
    public static void main(String args[]) throws IOException 
        ServerSocket server = new ServerSocket(8080);
        while (true) 
            try (Socket socket = server.accept()) 
                Date today = new Date();
                String httpResponse = "HTTP/1.1 200 OK\r\n\r\n" + today;
                socket.getOutputStream().write(httpResponse.getBytes("UTF-8"));
            
        
    

从浏览器转到http://127.0.0.1:8080/,您将获得当前日期。

【讨论】:

【参考方案2】:
writer.println("Hello");

您没有发送任何换行符。此外,您的“应该有效”跟踪位于错误的位置。应该在flush()之后。

你也没有阅读回复。

此外,服务器只会显示 POST ... 或 PUT ...,而不是您发送的行。因此,除非您 (a) 使服务器具有 HTTP 意识或 (b) 摆脱无法使用 Socket 的疯狂限制,否则这永远不会起作用。 为什么你不能使用 Socket?

编辑:我的代码版本如下:

    static class Server implements Runnable
    

        public void run()
        
            try
            
                ServerSocket serverSock = new ServerSocket(62666);
                for (;;)
                
                    Socket sock = serverSock.accept();
                    System.out.println("From IP: " + sock.getInetAddress());
                    BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
                    PrintWriter writer = new PrintWriter(sock.getOutputStream());
                    String line;
                    while ((line = reader.readLine()) != null)
                    
                        System.out.println("\t:" + line);
                    
                    writer.println("Testing123");
                    writer.close();
                    reader.close();
                    System.out.println("Server exiting");
                    serverSock.close();
                    break;
                
            
            catch (IOException e)
            
                e.printStackTrace();
            
        
    

    static class Client implements Runnable
    

        public void run()
        
            try
            
                URL url = new URL("http://127.0.0.1:62666");
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setDoOutput(true);
//              connection.setRequestMethod("POST");
                connection.connect();
                PrintWriter writer = new PrintWriter(connection.getOutputStream());
                writer.println("Hello");
                writer.flush();
                System.out.println("flushed");
                int responseCode = connection.getResponseCode();
                writer.close();
                BufferedReader  reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                System.out.println("closed");
                System.out.println("response code="+responseCode);
                String  line;
                while ((line = reader.readLine()) != null)
                    System.out.println("client read "+line);
                reader.close();
                System.out.println("Client exiting");
            
            catch (IOException e)
            
                e.printStackTrace();
            
        
    

    public static void  main(String[] args)
    
        Thread  t = new Thread(new Server());
        t.setDaemon(true);
        t.start();
        new Client().run();
        System.out.println("Main exiting");
    

【讨论】:

这也是我的第一个想法,但这不是问题。 @Ryan Stewart 这里的 println 存在更大的问题。该服务器不可能显示该数据。 你能解释一下为什么吗?我不知所措。 “你好”去哪儿了? @Ryan Stewart 因为它只读取和打印一行,这是第一个 HTTP 标头。它需要读取和显示,直到 readLine() 返回 null。注意 not 直到 readLine() 返回一个空行:这仅表示标题的结尾。接下来是你的“你好”。 你真的运行过这个程序吗?在问题中发布的表单中,它不输出任何内容,因为它从不发送任何内容。通过一些更改,您可以让它发送和接收完整的 HTTP 请求,但“Hello”永远不会出现在任何地方。【参考方案3】:

我无法弄清楚到底发生了什么。 OutputStream 有一些有趣的地方。添加一个

((HttpURLConnection) connection).getResponseCode();

connect() 之后和close() 之前的某个位置,您应该会看到一些不同的东西,如果不是您所期望的。

也许您不应该尝试将 HTTP 用作 hack,而应该使用完整的 HTTP。像您一样使用来自客户端的 HTTP,并在服务器上设置嵌入式 HTTP 服务器。有几个可供选择,实际上只需要几行即可运行:例如Grizzly、Simple Framework 或Jetty。

【讨论】:

这输出:POST / HTTP/1.1 From IP: /127.0.0.1 所以,基本上是 POST / HTTP/1.1。 (IP部分是我添加的)。我正在考虑像你说的那样让服务器应用程序完全使用 HTTP,如果这很容易的话。不过,如果这会导致任何地方,我宁愿避免它。 @Mike:我还没有发现它可以领导任何地方。如果你把你的 readLine() 放入一个循环中,你最终会打印出一个完整的 HTTP 请求,但是你的“Hello”行神秘地不存在。无论我尝试过什么,似乎您自己写入该 OutputStream 的任何内容都会消失。【参考方案4】:

如果您希望客户端使用 URL 连接向服务器发送消息,我认为这是您需要做的:

public class Client

    public Client()
    
        try
        
            url = new URL("http://127.0.0.1:62666");
            URLConnection urlConnection = url.openConnection();
            PrintWriter writer = new PrintWriter(urlConnection.getOutputStream());
            writer.println("Hello World!");
            writer.flush();
            writer.close();
        catch(Exception e)e.printStackTrace();
    

现在是服务器:

public class Server implements Runnable

    public Server()
    
        ServerSocket server = new Server(62666);
        client = server.accept();
        new Thread(this).start();  
    

    public void run()
    
        try
        
            String message;
            BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()))
            while((message=reader.readLine())!=null)
            
                System.out.println("Message from client: "+message);
            
        catch(Exception e)
        
            System.out.println("Client disconnected");
        
    
    Socket client;

【讨论】:

我不明白这应该如何工作:/.. 如果您仔细查看我发布的内容,我正在做的基本上是一样的。看不出有什么大的不同。不过还是谢谢。 @Mike Haye 如果仔细观察,你会发现至少有两个主要区别。他省略了 doOutput(true) 但还有另一个。 @EJP:我看到的唯一区别是这段代码有几个语法错误,并且由于 doOutput 为假而失败。还是不行。 @Ryan Stewart 所以你错过了 print/println 的区别。 @EJP:我没有错过。这没什么区别。试试看。

以上是关于Java - 通过浏览器/URL 连接到 ServerSocket的主要内容,如果未能解决你的问题,请参考以下文章

使用 gitlab java api 连接到 gitlab

通过主机名连接到 Java 套接字

无法使用 java 连接到 HTTPS url

通过SSL将IBM DB2 JDBC连接到编目数据库

Apache Drill - 以嵌入式模式连接到 Drill [java]

电脑安装Java,提示找不到URL,怎么解决?