【问题标题】:java socket writing to and then reading from socketjava套接字写入然后从套接字读取
【发布时间】:2015-02-23 14:38:08
【问题描述】:

我正在尝试用 java 编写一个简单的 http 服务器。到目前为止,这是我的代码:

服务器:

import java.net.*;
import java.io.*;
import java.util.*;
import java.util.regex.*;

public class Server
{
    static final int PORT = 8080;
    final String REQUEST_FORMAT = "^GET (.*?) HTTP/1.1$";
    final Socket client;

    public Server(Socket s)
    {
        client = s;
    }

    public void run()
    {
        try
        (Scanner in = new Scanner(new InputStreamReader(client.getInputStream()));
        PrintWriter out = new PrintWriter(client.getOutputStream(),true);)  
        {
            String request = in.findInLine(Pattern.compile(REQUEST_FORMAT));
            System.out.println(request);
            out.write("HTTP/1.1 200 OK");   
        }
        catch(Exception ex)
        {   
            ex.printStackTrace();               
        }
    }

    public static void main(String []args)
    {
        try
        (
        ServerSocket server = new ServerSocket(PORT);
        Socket client = server.accept();
        )
        {
            Server s = new Server(client);
            s.run();
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
    }
}

客户:

import java.net.*;
import java.io.*;
import java.util.*;

public class Client
{
    final int PORT = 8080;
    String data = "GET /home/index.html HTTP/1.1";
    public Client()
    {
        try
        (Socket socket = new Socket("127.0.0.1",PORT);
        PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
        Scanner in = new Scanner(new InputStreamReader(socket.getInputStream()));)
        {
            out.print(data);
            String header1 = in.next();
            System.out.println("header="+header1);
            int status = in.nextInt();
            System.out.println("status="+status);
            String message = in.next();
            System.out.println("message="+message); 
        }
        catch(Exception ex)
        {
        }

    }

    public static void main(String []args)
    {
        Client c = new Client();
    }
}

目前客户端只向服务器写入一个示例请求,服务器写入一个示例响应头。但是服务器在读取请求后似乎无限地等待客户端输入而没有继续发送响应。请帮助解决这个问题。

【问题讨论】:

    标签: java sockets


    【解决方案1】:

    如果您要实现 HTTP 服务器,则需要实现 HTTP 协议。你没有那样做。您需要仔细查看 RFC 2616,特别是有关内容长度标头、连接:关闭和分块传输编码的部分,它们是确定传输内容长度的不同方法。

    你也没有在任何时候写行。 HTTP 中的行终止符是 \r\n,,它不会出现在代码中的任何位置。

    还有其他问题。您的服务器将只接受一个客户端然后停止。它需要围绕接受代码进行循环,并且需要启动一个新线程来处理每个连接。

    【讨论】:

    • 我没有实现一个实际的 HTTP 服务器。我是一名学生,这应该是一个“简单”的 HTTP 服务器——值得分配几个小时。无论如何,感谢您的帮助。
    • 您仍然需要行终止符,您仍然需要读取行,并且您仍然需要在每个服务器会话中处理多个客户端。如果您认为在实现任何类型的 HTTP 服务器时可以忽略 HTTP 规范,那您就错了。
    • 是的,我需要行终止符。谢谢你指出这一点。那是我的错误。我查看了this link 并没有完全阅读它,得出的结论是请求末尾没有换行符。我还有很多东西要实现,不仅要处理更多的客户端,而且我必须实现一个线程池来处理客户端。但我想我会先做基本的然后看看。非常感谢您的帮助。
    【解决方案2】:

    你的服务器阻塞在

    String request = in.findInLine(Pattern.compile(REQUEST_FORMAT));
    

    原因是模式没有找到,流也没有结束。

    解决方案A:关闭客户端写入的socket

    out.print(data);
    socket.shutdownOutput();
    

    这仅在您不想在客户端进行进一步写入时才有效。

    解决方案 B

    1. 客户端:在数据后写入换行符。

      out.print(data);
      out.print("\r\n");
      out.flush();
      
    2. 服务器:使用 Scanner.nextLine() 和 Matcher 而不是 Scanner.findInLine()

      String line = in.nextLine();
      Matcher matcher = Pattern.compile(REQUEST_FORMAT).matcher(line);
      String request = null;
      if(matcher.find()) {
          //request = line.substring(matcher.start(),matcher.end());
          request = matcher.group();//is similar to the commented line above
      }
      

    【讨论】:

    • 但是如果我在最后写换行符是不是错了。据我所知,HTTP GET 请求末尾没有换行符?
    • @PPGoodMan 你错了。不要做出没有证据的猜测。
    • 你试过实现一个简单的socket服务器和socket客户端吗?它奏效了吗?从那里您可以进行改进,使其看起来像一个 Http 套接字服务器
    • @EJP 是的,那是我的错误。最后我需要换行符。我查看了this page 的顶部,得出了一个轻率的结论,即 GET 请求末尾没有换行符。谢谢你的回复。
    猜你喜欢
    • 2015-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-12
    • 1970-01-01
    • 2017-09-10
    • 2012-02-03
    • 2022-01-25
    相关资源
    最近更新 更多