java写的简单的HTTP服务器,firefox下访问时会提示连接被重置

wuliuxu 2013-06-17 02:31:01
使用java实现的HTTP服务器响应功能。但是在通过firefox反复刷新访问localhost:8416时,有时可以得到正常的响应,但更多的时候无法得到正常响应,浏览器显示连接被重置

代码如下:

首先是main函数:
public static void main(String[] args) {
int port = 8416;
int backlog = 500;
int acceptCount = 0;
Socket serverSocket = null;

try {
ServerSocket httpServer = new ServerSocket(port, backlog);
System.out.println("server:httpy");

while(true){
// 从等待队列中取出一个连接请求,建立socket连接
serverSocket = httpServer.accept();
acceptCount ++;

// 对每次客户端的请求都使用一个独立的线程来响应
HttpResponse response = new HttpResponse(serverSocket);
Thread thread = new Thread(response);
thread.start();

// 打出服务端已经接受并处理请求数
System.out.println(acceptCount);
}
} catch (IOException e) {
e.printStackTrace();
}
}

然后是服务端进行响应的线程类(HttpResponse):
class HttpResponse implements Runnable{
// 与客户端进行连接的socket
Socket serverSocket = null;
// 回车换行
String crlf = "\r\n";
// 服务端进行响应的输出流
BufferedWriter responseWriter = null;
BufferedReader br = null;

HttpResponse(Socket _socket){
serverSocket = _socket;
}

public void run(){
response();
}

/**
* 对客户端请求进行响应的处理方法
*
* @param none
* @return none
*/
public void response(){
try{
responseWriter =
new BufferedWriter(
new OutputStreamWriter(
serverSocket.getOutputStream()));
// 服务端进行响应的响应内容
StringBuffer content = new StringBuffer();
content.append("<html>");
content.append("<head>");
content.append("<title>");
content.append("httpy web server");
content.append("</title>");
content.append("</head>");
content.append("<body>");
content.append("<div>");
content.append("<a>server:httpy</a>");
content.append("</div>");
content.append("</body>");
content.append("</html>");

// 服务端进行响应的响应头
StringBuffer header = new StringBuffer();
header.append("HTTP/1.1 200 OK");
header.append(crlf);
header.append("Content-Length:");
header.append(content.toString().getBytes("utf-8").length);
header.append(crlf);
header.append("Content-Type:text/html;UTF-8");
header.append(crlf);
header.append(crlf);

// 输出响应头
responseWriter.write(header.toString());
// 输出响应内容
responseWriter.write(content.toString());

} catch (Exception e) {
e.printStackTrace();
}finally{
// 关闭资源连接
try {
if(responseWriter != null){
responseWriter.close();
}

if(serverSocket != null){
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}


客户端访问
使用浏览器:firefox
访问地址 :localhost:8416

如果反复快速的进行访问(不管是反复回车请求,F5刷新请求,还是Ctrl + F5刷新请求),就会出现,有时浏览器得到正常页面显示,而更多的时候却显示连接被重置,不知道是什么原因导致的。

以下是页面正常显示的效果:


以下是请求异常的时候页面显示的效果:


另外,本人下载了一个java开源的HTTP服务器项目,在本机上测试时一切正常,排除浏览器,系统环境的影响。
...全文
850 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
wuliuxu 2013-07-21
  • 打赏
  • 举报
回复
今天抽了个时间进行了测试,验证了如下描述:
socket在自身接收缓冲区仍存在数据的情况下关闭时会导致发出RST数据包。
上例中,由于服务端没有对接收缓冲区的数据进行读取,这样,服务端只要关闭socket,就会向客户端发送一个RST包。


至于浏览器为什么有时显示正常,有时又显示未连接被重置。由于本人不清楚浏览器接收到RST包后内部会做何种处理,只能对该现象做出一个可能的推测:
TCP协议规定,RST包可以优先于发送缓冲区的数据包发出,这样,如果服务端在发送缓冲区中的数据还未发出前(发出部分算不算这个我还不能肯定)就关闭了socket,那产生的RST就会立即发送给浏览器端,浏览器端接收到RST肯定也会断开本端的连接,停止接收数据,由于浏览器接收不到服务器响应的数据包,这样就无法显示任何消息,只能给出连接被重置的信息。 但如果服务端RST包在发送给浏览器端之前,服务端发送缓冲区的内容(也就是响应内容)已经全部发到浏览器端的接收缓冲区,这样浏览器已经接收到响应消息就能正常显示网页内容。

wuliuxu 2013-06-24
  • 打赏
  • 举报
回复
这几天做别的事没好好处理这个问题,不过最近看到这样一篇介绍好像能很好的解释我所遇到的问题,链接是:http://my.oschina.net/costaxu/blog/127394,其中介绍的第3中发送RST的情况大概就是我这种情况,大概意思也跟fei1710先前的说法类似。最近事较多没来得及验证,验证主要是解释下面两个问题: 1、服务端发送RST包的情况; 2、浏览器在接到RST包后显示正常与异常的时机问题。 初步解释参考上面链接的第3点,测试待续,测试完毕就结贴..
wuliuxu 2013-06-21
  • 打赏
  • 举报
回复
感谢shnulaa,辛苦做了这么多测试。其实,发帖之前我也考虑过你说的这种原因——服务端在客户端未获取到全部数据前就关闭socket引发异常。但是之后发现这个分析还是有疑点: 1、按照TCP/IP的4次握手原则,主动关闭的一方在发送fin包之后会停止向接收方发送数据,而被动关闭的一方在接到fin包之后也不再从主动关闭的一方那里读取数据,那出现了上面的情况到底是哪个环节出了问题呢? 2、我之前也试过在关闭前让线程sleep一会给客户端留出时间,但是后来一想,服务器在设计的时候真的会在close前sleep一段时间吗,服务器要的就是快速响应,阻塞一段时间的做法就是在降低响应速度,而且,从我下的一个开源的HTTP服务器来看,它的服务端完全没有采取sleep之类的做法。 3、我在7楼提供了一种解决方法,就是在服务端添加一个BufferReader来读取客户端发送的消息,问题就不会出现了,不用sleep,也不用在客户端接受服务端关闭信息。如果是因为服务端提前关闭的原因,上面这种做法是无法掩盖问题的。 当然,shnulaa所作的分析确实揭示了问题的一个现象,后续的分析我觉得需要结合这两种解决方法分析,当然还是感谢各位的解答。 待续..
晓风吹雾 2013-06-21
  • 打赏
  • 举报
回复

String line = null;
while ((line = reader.readLine()) != null) {
    System.out.println(line);
}
改成

String line = null;
while (!(line = reader.readLine()).isEmpty()) {
    System.out.println(line);
}
当接收到空字符串的时候就退出等待
晓风吹雾 2013-06-21
  • 打赏
  • 举报
回复
加几个细节的问题,调试了一下代码,发现reader.readLine()的block分成2个部分,客户端读取第一部分

 POST / HTTP/1.1
 Content-Length: 0
 Host: 192.168.1.83:8416
 Connection: Keep-Alive
的时间节点是在读取服务端的response之前。 之后的第二部分又会block,这次block的release是在客户端的connection关闭后release.也就是在以下代码之后

 if (httpPost != null) {
    httpPost.releaseConnection();
 }
 if (httpClient != null) {
    httpClient.getConnectionManager().shutdown();
 }
这也就保证了服务端的socket in out的关闭是在客户端主动关闭以后服务端才释放资源的。
晓风吹雾 2013-06-21
  • 打赏
  • 举报
回复
这个问题有点意思,所以大致看了一下。 需要分析原因 1 用浏览器不大好分析原因,所以使用httpclient模拟浏览器来进行模拟多用户并发提交 以下是具体的代码,主要是模拟n个线程来提交m个http request.

 import java.io.IOException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.client.params.HttpClientParams;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
 import org.apache.http.params.BasicHttpParams;
 import org.apache.http.params.HttpConnectionParams;
 import org.apache.http.params.HttpParams;
 import org.apache.http.util.EntityUtils;
 
 public class HttpClientTest {
 
     /**
      * @param args
      * @throws InterruptedException
      */
     public static void main(String[] args) throws InterruptedException {
         ExecutorService service = null;
         try {
             service = Executors.newFixedThreadPool(100);
             final Runnable runnableImpl = new Runnable() {
                 public void run() {
                     System.out.println(Thread.currentThread().getName());
                     postCommunication("http://192.168.1.83:8416/");
                 }
             };
             for (int i = 0; i < 100; i++) {
                 service.submit(runnableImpl);
             }
 
             service.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
         } finally {
             if (service != null) {
                 service.shutdown();
             }
         }
     }
 
     public static final void postCommunication(final String url) {
         DefaultHttpClient httpClient = null;
         HttpPost httpPost = null;
         String bodyMessage = null;
         int statusCode = -1;
         try {
             // create instance httpClient with hTTP parameter
             // set the retry handler
             httpClient = new DefaultHttpClient(setParam());
             httpClient
                     .setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(
                             0, false));
             // create post instance
             httpPost = new HttpPost(url);
 
 //            httpPost.addHeader("Connection", "close");
 
             // get the status code and body message.
             HttpResponse response = httpClient.execute(httpPost);
             statusCode = response.getStatusLine().getStatusCode();
             HttpEntity reEntity = response.getEntity();
             if (reEntity != null) {
                 bodyMessage = EntityUtils.toString(reEntity);
             }
         } catch (IOException e) {
             e.printStackTrace();
         } catch (Exception e) {
             e.printStackTrace();
         } finally {
             if (httpPost != null) {
                 httpPost.releaseConnection();
             }
             if (httpClient != null) {
                 httpClient.getConnectionManager().shutdown();
             }
         }
         System.out.println("statusCode:" + statusCode + ",bodyMessage:"
                 + bodyMessage);
     }
 
     private static final HttpParams setParam() {
         final HttpParams httpParams = new BasicHttpParams();
         HttpConnectionParams.setConnectionTimeout(httpParams, 2000);
         HttpConnectionParams.setSoTimeout(httpParams, 2000);
         HttpConnectionParams.setSocketBufferSize(httpParams, 1024 * 2);
         HttpClientParams.setRedirecting(httpParams, true);
 
         return httpParams;
     }
 }
以上的代码模拟100个用户并发执行100个http request. 但是经常会出现问题。 错误为以下
java.net.SocketException: Software caused connection abort: recv failed
这是什么原因呢,那我们就分析一下。 首先看一下出错在什么地方。 我们的代码错误在

 HttpResponse response = httpClient.execute(httpPost);
 
到底在什么情况下出现这种问题,那就看一下httpclinet的源代码。 发现在这种情况下会出现错误。 1 server端

 responseWriter.write(header.toString());
 responseWriter.write(content.toString());
 
以后会立即关闭responseWriter 2 客户端httpclient在read response的时候根本还没有来得及read的时候,因为服务端已经主动关闭了。抛出了IOException httpclient出错的具体位置

  DefaultHttpResponseParser.java
  method parseHead
  int i = sessionBuffer.readLine(this.lineBuf); // 这里出错了,由于服务端的socketoutputstream已经关闭了 这里的sessionBuffer readline也就会抛出io exception.
  
所以说总结一下,出现这种错误的原因是因为当服务端向socket写数据的时候,由于没有等待客户端的读数据操作完成,就关闭了socket的outputstream和socket对象,导致客户端抛出了异常 下面说一下解决方法 解决方法 我想是不是可以在服务端写数据以后,有一个缓冲的时间,让客户端将数据读好呢。所以就先加了一个thread.sleep,这样测试下来,错误明显减少了不少,但是这并不能解决根本的问题 所以想当客户端将response读完以后,肯定对服务端有个回应才对,即告诉服务端我这边已经读取好了,你可以关闭了,所以在再服务端的代码中加入了对socket inputstream的读取,是加载write以后的。代码比较简单,如下

 BufferedWriter responseWriter = null;
 BufferedReader reader = null;
 
 try {
     responseWriter = new BufferedWriter(new OutputStreamWriter(
     socket.getOutputStream()));
     reader = new BufferedReader(new InputStreamReader(
     socket.getInputStream()));
 
     StringBuffer content = new StringBuffer();
     content.append("<html>");
     content.append("<head>");
     content.append("<title>");
     content.append("httpy web server");
     content.append("</title>");
     content.append("</head>");
     content.append("<body>");
     content.append("<div>");
     content.append("<a>server:httpy</a>");
     content.append("</div>");
     content.append("</body>");
     content.append("</html>");
 
     StringBuffer header = new StringBuffer();
     header.append("HTTP/1.1 200 OK");
     header.append(BR);
     header.append("Content-Length:");
     header.append(content.toString().getBytes("utf-8").length);
     header.append(BR);
     header.append("Content-Type:text/html;UTF-8");
     header.append(BR);
     header.append(BR);
 
     responseWriter.write(header.toString());
     responseWriter.write(content.toString());
     
     // 这里的flush也是必须的。
     responseWriter.flush(); 
     // Thread.sleep(10);
     
     // 这里等待客户端读取完response返回通知。
     String line = null;
     while ((line = reader.readLine()) != null) {
          System.out.println(line);
     }
 
 } catch (Exception e) {
     e.printStackTrace();
 } finally {
     try {
 if (responseWriter != null) {
     responseWriter.close();
 }
     } catch (IOException e) {
 e.printStackTrace();
     }
 
     try {
 if (socket != null) {
     socket.close();
 }
     } catch (IOException e) {
 e.printStackTrace();
     }
 }
 
综上所述,修改好以上的代码,1000线程做1000个http request也是没有什么问题的。代码可以优化的地方 thread的地方可以使用线程池,不需要一个request对应一个thread.只需要线程池就可以了。
fei1710 2013-06-19
  • 打赏
  • 举报
回复
引用 9 楼 wuliuxu 的回复:
[quote=引用 8 楼 fei1710 的回复:] [quote=引用 6 楼 wuliuxu 的回复:] [quote=引用 5 楼 fei1710 的回复:] 貌似当接收缓存区还存在数据时关闭socket会导致异常关闭,即发送RST立即关闭TCP连接。 当接收方收到RST时系统会丢弃TCP的发送和接收缓冲区,如果在此之前浏览器进程没有完全接收TCP缓冲区的数据的话,数据就不完整,浏览器就会报错。因为你没读取发送的数据,所以会出现这种情况。
我想确认一下,你说的接受缓存区是指服务端的接收缓存区,还是指客户端(浏览器)的接收缓存区。测试中,如果在服务端添加读取socket接收缓冲区的代码后,问题就消息了,从这个现象上看,有点支持你的观点。但问题是,上面的代码中,服务端根本就没有读取自身接收缓存区的数据,如果是你说的这个原因,那么,测试的时候,应该一次也不会成功,但为什么测试的结果却是有时成功,有时失败呢?[/quote] 这是一个时机问题,如果在收到RST之前已经读取了接收缓冲区的数据就不会报错,否则就会报错。 我测试了一下java下报的是这个错误 java.net.SocketException: Software caused connection abort: recv failed at java.net.SocketInputStream.socketRead0(Native Method)[/quote] 我想再次确认一下,你说的缓冲区(上面加粗加下划线标明)是指服务端的缓冲区还是客户端(浏览器)的缓冲区? [/quote] socket缓冲区
wuliuxu 2013-06-19
  • 打赏
  • 举报
回复
引用 8 楼 fei1710 的回复:
[quote=引用 6 楼 wuliuxu 的回复:] [quote=引用 5 楼 fei1710 的回复:] 貌似当接收缓存区还存在数据时关闭socket会导致异常关闭,即发送RST立即关闭TCP连接。 当接收方收到RST时系统会丢弃TCP的发送和接收缓冲区,如果在此之前浏览器进程没有完全接收TCP缓冲区的数据的话,数据就不完整,浏览器就会报错。因为你没读取发送的数据,所以会出现这种情况。
我想确认一下,你说的接受缓存区是指服务端的接收缓存区,还是指客户端(浏览器)的接收缓存区。测试中,如果在服务端添加读取socket接收缓冲区的代码后,问题就消息了,从这个现象上看,有点支持你的观点。但问题是,上面的代码中,服务端根本就没有读取自身接收缓存区的数据,如果是你说的这个原因,那么,测试的时候,应该一次也不会成功,但为什么测试的结果却是有时成功,有时失败呢?[/quote] 这是一个时机问题,如果在收到RST之前已经读取了接收缓冲区的数据就不会报错,否则就会报错。 我测试了一下java下报的是这个错误 java.net.SocketException: Software caused connection abort: recv failed at java.net.SocketInputStream.socketRead0(Native Method)[/quote] 我想再次确认一下,你说的缓冲区(上面加粗加下划线标明)是指服务端的缓冲区还是客户端(浏览器)的缓冲区?
fei1710 2013-06-19
  • 打赏
  • 举报
回复
引用 6 楼 wuliuxu 的回复:
[quote=引用 5 楼 fei1710 的回复:] 貌似当接收缓存区还存在数据时关闭socket会导致异常关闭,即发送RST立即关闭TCP连接。 当接收方收到RST时系统会丢弃TCP的发送和接收缓冲区,如果在此之前浏览器进程没有完全接收TCP缓冲区的数据的话,数据就不完整,浏览器就会报错。因为你没读取发送的数据,所以会出现这种情况。
我想确认一下,你说的接受缓存区是指服务端的接收缓存区,还是指客户端(浏览器)的接收缓存区。测试中,如果在服务端添加读取socket接收缓冲区的代码后,问题就消息了,从这个现象上看,有点支持你的观点。但问题是,上面的代码中,服务端根本就没有读取自身接收缓存区的数据,如果是你说的这个原因,那么,测试的时候,应该一次也不会成功,但为什么测试的结果却是有时成功,有时失败呢?[/quote] 这是一个时机问题,如果在收到RST之前已经读取了接收缓冲区的数据就不会报错,否则就会报错。 我测试了一下java下报的是这个错误 java.net.SocketException: Software caused connection abort: recv failed at java.net.SocketInputStream.socketRead0(Native Method)
wuliuxu 2013-06-19
  • 打赏
  • 举报
回复
非常感谢u010255083的辛苦测试和解答,提供的博文也非常的有用。结合你的测试和分析来看,好像问题集中到了“客户端为什么会发一个RST报文这点了”,接下来我得再好好考虑这点了。
火影之贺 2013-06-19
  • 打赏
  • 举报
回复
http://blog.csdn.net/sureyonder/article/details/5633647 网上又找了个文章看看,希望对你有帮助!
火影之贺 2013-06-19
  • 打赏
  • 举报
回复
兄弟你的问题太有意思了。我之前测试,确实只是间隔的刷新页面,没有持续的刷新。

这次测试,使用ie按住f5键,后台有对应的错误日志:
938
939
java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:202)
at sun.nio.cs.StreamEncoder.implClose(StreamEncoder.java:297)
at sun.nio.cs.StreamEncoder.close(StreamEncoder.java:130)
at java.io.OutputStreamWriter.close(OutputStreamWriter.java:216)
at java.io.BufferedWriter.close(BufferedWriter.java:248)
at httpserver.HttpResponse.response(HttpResponse.java:76)
at httpserver.HttpResponse.run(HttpResponse.java:24)
at java.lang.Thread.run(Thread.java:619)
940
941
942

因为ie不断的刷新,所以肉眼比较难分辨出对应这个错误日志时ie展示了什么。

不过我有抓包如下:

请求有167往165发起

图中,从上往下看,是三次请求,在最左边我用三个方框标了出来。
第一次正常的,第二次异常,第三次正常(就没给出完整的截图)。

因为http基于tcp,所以每个http报文前肯定要经过tcp三次握手,http结束后要有4个tcp断开的报文(暂时不关心)。图中小圆形标出来的,就是http之前的三次握手。最后一列椭圆形就是握手过程的几个关键flag。

再看第一个小圆形下方紧跟着的http请求和响应,就是HTTP GET和HTTP 200OK。可见第一个请求是正常的。

看第二个小圆形下方紧跟着的http请求,只有HTTP GET,没见到200 OK。14405这一行,我用一个椭圆和一个长方形标了出来,其中有个RST报文。
网上摘录一段话“RST一般是在FIN之后才会出现为1的情况,表示的是连接重置。”
我想:如果连接都重置了,服务器端就会出现写失败。正好和上面的错误日志吻合。

那么现在只是抓包和日志对上了,但是为什么客户端会发一个RST的报文,我就不清楚了。
wuliuxu 2013-06-18
  • 打赏
  • 举报
回复
还有下面一条测试线索: 如果加入以下代码($$$$$$$$$$$$$$$$$$$$$$$$标示出的中间部分),问题就消息了。 [下面是加入新代码后的程序片段,其他地方都不作改变]

public void response(){
        try{
            responseWriter = 
                    new BufferedWriter(
                            new OutputStreamWriter(
                                    serverSocket.getOutputStream()));


            // 此处是新加入的代码片段$$$$$$$$$$$$$$$$$$$$$$$$
            br = 
                    new BufferedReader(
                            new OutputStreamReader(
                                    serverSocket.getInputStream()));
            br.read();
            // 以上是新加入的代码片段$$$$$$$$$$$$$$$$$$$$$$$$



            // 服务端进行响应的响应内容
            StringBuffer content = new StringBuffer();
            content.append("<html>");
wuliuxu 2013-06-18
  • 打赏
  • 举报
回复
引用 5 楼 fei1710 的回复:
貌似当接收缓存区还存在数据时关闭socket会导致异常关闭,即发送RST立即关闭TCP连接。 当接收方收到RST时系统会丢弃TCP的发送和接收缓冲区,如果在此之前浏览器进程没有完全接收TCP缓冲区的数据的话,数据就不完整,浏览器就会报错。因为你没读取发送的数据,所以会出现这种情况。
我想确认一下,你说的接受缓存区是指服务端的接收缓存区,还是指客户端(浏览器)的接收缓存区。测试中,如果在服务端添加读取socket接收缓冲区的代码后,问题就消息了,从这个现象上看,有点支持你的观点。但问题是,上面的代码中,服务端根本就没有读取自身接收缓存区的数据,如果是你说的这个原因,那么,测试的时候,应该一次也不会成功,但为什么测试的结果却是有时成功,有时失败呢?
fei1710 2013-06-18
  • 打赏
  • 举报
回复
貌似当接收缓存区还存在数据时关闭socket会导致异常关闭,即发送RST立即关闭TCP连接。 当接收方收到RST时系统会丢弃TCP的发送和接收缓冲区,如果在此之前浏览器进程没有完全接收TCP缓冲区的数据的话,数据就不完整,浏览器就会报错。因为你没读取发送的数据,所以会出现这种情况。
wuliuxu 2013-06-17
  • 打赏
  • 举报
回复
感谢u010255083的辛苦测试,但是我机器上使用IE跑,还是会出现问题,不过显示的不是连接被重置,而是“无法显示当前页面”。你是怎么测试的,有没有反复的刷新,就是按着F5不动。浏览器断断续续的请求几次可能没问题,高频率的刷新问题就出现了。期待u010255083再测试一次,是高频率刷新哦
火影之贺 2013-06-17
  • 打赏
  • 举报
回复
拷贝到本机并运行了,因为没有装firefox浏览器,我只用了IE和chrome这2个浏览器测试。 测试结果一切正常。google了“firefox 连接被重置”,好多人都遇到了类似的问题。 建议楼主也可以从firefox这里找找原因,不一定是你的代码的问题。 http://www.elecbench.com/?p=268 最后找到了真正的解决办法,应该是火狐的一些设置或插件的问题。办法如下:删除C:\Documents and Settings\Administrator\Application Data\目录下Mozilla文件夹。前提是你没有安装Mozilla的其他软件。
wuliuxu 2013-06-17
  • 打赏
  • 举报
回复
我是一只掉队的程序员,没工作,没朋友,没机器,就一个人呆在住的地方敲代码学习。其实程序所有的代码就上面那一点,各位不介意可以copy到自己的机器上跑跑看,整个过程大概耗时30秒。
晓风吹雾 2013-06-17
  • 打赏
  • 举报
回复
试试不要再一台机器上发布http server和访问这个http server. 可以换换将server发布到局域网的另外的机器,然后访问。

51,395

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧