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

3

我正在编写一款软件,但受到限制,不能使用socket来连接使用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 Stewart
服务器是否收到消息? - gsfd
@ryan:我知道。很难解释。简单来说,我不能直接实例化Socket对象。@john:不是这样的。似乎每当我运行应该连接到它的应用程序时,服务器都会“卡住”。每当我尝试通过浏览器之后连接到ServerSocket时,它就一直在尝试连接。 - Mike Haye
迈克,你最终找到了解决方法吗?我很想知道你发现了什么或选择了做什么。 - Ryan Stewart
我从未找到使用URL的有效方法。对于我正在做的事情,目前不允许我实例化套接字对象,所以我基本上一无所获。感谢您的关注 :) - Mike Haye
显示剩余2条评论
4个回答

2

以下是一个非常不错的示例

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/,您将获得当前日期。


1

我无法确定问题出在哪里。那个OutputStream有点儿奇怪。请添加一个

((HttpURLConnection) connection).getResponseCode();

connect()之后和close()之前的某个地方,你应该看到一些不同的东西,如果没有你预期的结果。

也许你不应该试图使用HTTP来进行hack,你应该完全使用HTTP。从客户端使用HTTP,然后在服务器上设置一个嵌入式HTTP服务器。市面上有几种选择,只需要几行代码就可以运行起来,例如:GrizzlySimple Framework 或者 Jetty


这将输出:POST / HTTP/1.1 来自 IP:/127.0.0.1所以,基本上是POST / HTTP/1.1。(IP部分由我添加)。如果这很容易实现的话,我正在考虑让服务器应用程序完全使用HTTP。如果这会导致任何问题,我宁愿避免。 - Mike Haye
@Mike:我发现这样做没有任何效果。如果你将readLine()放入循环中,你最终会打印出完整的HTTP请求,但是你的“Hello”行神秘地消失了。无论我尝试什么,似乎你自己写入OutputStream的任何内容都会消失。 - Ryan Stewart

0

如果您想让客户端使用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
@Mike Haye 如果仔细看的话,你会发现至少有两个主要的区别。他省略了doOutput(true),但还有另一个区别。 - user207421
@EJP:我看到的唯一区别是这段代码有几个语法错误,并且它失败了,因为doOutput是false。但它仍然无法正常工作。 - Ryan Stewart
@EJP:抱歉,我应该说“在运行此代码时我看到的唯一区别”。 - Ryan Stewart
服务器没有接收到消息的原因是因为服务器从未调用reader.readLine()方法,这样服务器就无法读取消息。 - gsfd
显示剩余3条评论

0
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
你能解释一下为什么吗?我有点不知所措。"Hello" 去哪了? - Ryan Stewart
@Ryan Stewart因为它只读取并打印了一行,即第一个HTTP头。它需要读取并显示直到readLine()返回null。注意:不仅仅是直到readLine()返回一个空行:那只表示头部的结束。你的“Hello”就在下一行。 - user207421
你实际上运行了这个程序吗?在问题中发布的形式中,它不会输出任何内容,因为它从未发送任何内容。通过进行一些更改,您可以使其发送和接收完整的HTTP请求,但“Hello”永远不会出现在任何地方。 - Ryan Stewart
是的,我已经尝试过了。通过对println()进行更正并将服务器读取到EOS的所有内容,服务器可以看到包括"Hello"在内的所有内容。然而,由于这不是一个HTTP服务器,它不会返回有效的HTTP,因此getResponseCode()在客户端处停滞。这个练习的目的仍然完全不清楚。如果您不能使用Socket,则必须使用更高级别的传输方式,这使得服务器不正确。 - user207421
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接