Servlet中Socket.accept()阻塞,JSP页面间TCP数据共享陷入加载状态
问题分析与解决
你的代码卡在Socket insocket = socket.accept();的核心原因是逻辑完全错误,同时对Web应用的数据共享机制理解偏差:
为什么会持续加载?
ServerSocket.accept()的设计就是阻塞当前线程,直到有客户端主动连接到监听的端口。但你的Servlet代码里只创建了服务端Socket,没有任何客户端程序去连接4333端口,所以这个线程会一直挂起,永远执行不到后面的response.sendRedirect("receiver.jsp");,页面自然会持续加载。
你的场景根本不需要TCP Socket
JSP页面间共享数据是Web应用的基础需求,完全不需要手动建立TCP连接。Web容器(比如Tomcat)本身提供了多种成熟的机制,比手动写Socket可靠得多:
方案1:请求转发(适合单次请求内共享数据)
如果receiver.jsp只需要获取当前请求的提交数据,用请求转发替代重定向,直接把数据放到request属性中传递:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String first = request.getParameter("first_name"); String last = request.getParameter("last_name"); String name = first + " " + last; // 将数据存入request属性,转发后receiver.jsp可直接读取 request.setAttribute("fullName", name); // 请求转发到receiver.jsp(属于服务器内部跳转,不会改变浏览器URL) request.getRequestDispatcher("receiver.jsp").forward(request, response); }
在receiver.jsp中读取数据:
<% String fullName = (String) request.getAttribute("fullName"); %> <h3>您提交的姓名:<%= fullName %></h3>
方案2:HttpSession(适合跨请求共享数据)
如果必须用重定向(浏览器URL会改变,属于客户端跳转),可以把数据存入Session:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String first = request.getParameter("first_name"); String last = request.getParameter("last_name"); String name = first + " " + last; // 获取当前会话,存入数据 HttpSession session = request.getSession(); session.setAttribute("fullName", name); // 重定向到receiver.jsp response.sendRedirect("receiver.jsp"); }
在receiver.jsp中读取Session数据(用完建议移除,避免占用会话资源):
<% String fullName = (String) session.getAttribute("fullName"); if (fullName != null) { %> <h3>您提交的姓名:<%= fullName %></h3> <% // 移除已使用的Session属性 session.removeAttribute("fullName"); } %>
为什么不要用手动Socket实现?
- Web容器的每个请求都是独立线程,你在请求线程中创建
ServerSocket并阻塞,会占用容器线程资源,严重影响应用性能。 - 即使你编写客户端代码去连接这个端口,这种方式也完全冗余——HTTP本身就是基于TCP的,Web容器已经帮你处理了底层的通信逻辑。
- 多用户同时提交请求时,会出现端口占用冲突、线程阻塞等各种问题,完全不符合Web应用的并发设计。
内容的提问来源于stack exchange,提问作者hachi__man
相关产品推荐
相关产品推荐

