为什么 Java TCP 服务器接受封闭套接字?



我有一个接受TCP连接的A类,并将这个新套接字发送到线程B,在那里接收和发送来自该套接字的数据。

Class A{
Class b = new B();   
public void run()
{
b.start();
while(true){
Socket socket = serverSocket.accept();
if(socket==null || socket.isClosed())continue;
b.setSocket(socket);
}
}
}
Class B extends Thread{
Socket socket;
public void setSocket(Socket p_socket) throws IOException
{
if(socket!=null && !socket.isClosed())
{
try{
socket.close();
socket = null;
Thread.sleep(5);
}
catch(Exception ex)
{}
}
socket = p_socket;
inputStream = socket.getInputStream(); // Here I am getting socket.closed() exception very much.
}

这在过去效果很好,但现在最近我经常收到以下错误。

java.io.IOException: Socket Closed
at java.net.AbstractPlainSocketImpl.getInputStream(AbstractPlainSocketImpl.java:421)
at java.net.Socket$2.run(Socket.java:914)
at java.net.Socket$2.run(Socket.java:912)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.Socket.getInputStream(Socket.java:911)

我不明白为什么经过多年的正常工作现在会发生这种情况。这是由于网络问题还是线程相关?

更新: 这可能是与服务器相关的问题吗?因为同一应用程序正在其他服务器上运行,但他们没有这个问题。

整个设置概念看起来有点破碎。您不应该从外部"更改"资源,而该线程中可能仍有一些工作正在进行。更好的方法是将 Socket 封装到新的工作线程中:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class WrapHandler {
static public class Server {
private final ServerSocket          mSocket;
private final ArrayList<Handler>    mRunningHandlers    = new ArrayList<>();
public Server(final int pPort) throws IOException {
mSocket = new ServerSocket(pPort);
new Thread(() -> mainLoop()).start();
}
private void mainLoop() {
while (true) {
try {
@SuppressWarnings("resource") final Socket socket = mSocket.accept(); // do not close, do not handle with resource, socket will be closed by handler!
final Handler h = new Handler(socket, this);
handlerStarted(h);
} catch (final IOException e) {
e.printStackTrace(); // do something useful
}
}
}
synchronized void handlerStarted(final Handler pHandler) {
mRunningHandlers.add(pHandler);
}
synchronized void handlerEnded(final Handler pHandler) {
mRunningHandlers.remove(pHandler);
}
void handleException(final Handler pHandler, final Throwable pException) {
/* again do something useful */
}
}
static public class Handler {
private final Socket    mSocket;
private final Server    mServer;
public Handler(final Socket pSocket, final Server pServer) {
mSocket = pSocket;
mServer = pServer;
new Thread(() -> handleSocket()).start();
}
private void handleSocket() {
try {
handleData();
} catch (final IOException e) {
mServer.handleException(this, e);
} finally {
mServer.handlerEnded(this);
stop();
}
}
private void handleData() throws IOException {
mSocket.getInputStream().read();
/* data handling code here */
}
void stop() {
try {
mSocket.close();
} catch (final IOException e) { /* ignore or handle as you will */ }
}
}
}

相关内容

  • 没有找到相关文章

最新更新