为什么我的客户端套接字输入流接收消息是从服务器套接字输出流

时间:2017-12-09 03:55:54

标签: java multithreading sockets

这是生成服务器线程的SocketServer代码

public class ProcessorCorresponder {
protected final static Logger logger = LogManager.getLogger( ProcessorCorresponder.class );

private static int port = Integer.parseInt(PropertiesLoader.getProperty("appserver.port") == null ? "666" : PropertiesLoader.getProperty("appserver.port"));
private static int maxConnections = Integer.parseInt(PropertiesLoader.getProperty("appserver.maxconnections") == null ? "666" : PropertiesLoader.getProperty("appserver.maxconnections"));

public static void main(String[] args) {
    logger.info("Starting server .. " 
            + "[port->" + port 
            + ",databaseName->" + databaseName + "]");

    try (ServerSocket listener = new ServerSocket();) {
    listener.setReuseAddress(true);
    listener.bind(new InetSocketAddress(port));
    Socket server;

    int i = 0;

    while((i++ < maxConnections) || (maxConnections == 0)) {
        server = listener.accept();

        logger.debug(
                "New Thread listening on " + server.getLocalAddress().toString() + ":" + server.getLocalPort()
                + ", initiated from IP => " +  server.getInetAddress().toString() + ":" + server.getPort()
                );

        MySocketServer socSrv = new MySocketServer (server);

        Thread t = new Thread( socSrv );            
        t.start();
    }
    } catch (Exception ex) {
        logger.error("Error in ProcessorInterface", ex);
    }
}
}

服务器代码:这是一个处理一个连接的线程,有一个程序监视serversocket并根据需要旋转请求线程。

public class MySocketServer implements Runnable {
protected final static Logger logger = LogManager.getLogger(MySocketServer.class);

private final Socket server;

// because we are using threads, we must make this volatile, or the class will
// never exit.
private volatile boolean shouldContinue = true;

private StringBuffer buffHeartbeatMessage = new StringBuffer().append((char) 0).append((char) 0).append((char) 0)
        .append((char) 0).append((char) 0).append((char) 0);
private Heartbeat heartbeat = new Heartbeat(/* 60 */3000, buffHeartbeatMessage.toString());

public MySocketServer(Socket server) {
    this.server = server;
}

@Override
public void run() {
    try (BufferedReader in = new BufferedReader(new InputStreamReader(this.server.getInputStream()));
            BufferedOutputStream out = new HeartbeatBufferedOutputStream(this.server.getOutputStream(),
                    heartbeat)) {

        final StreamListener listener = new StreamListener(in);
        listener.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                if (event.getID() == ActionEvent.ACTION_PERFORMED) {
                    if (event.getActionCommand().equals(StreamListener.ERROR)) {
                        logger.error("Problem listening to stream.");
                        listener.setShouldContinue(false);
                        stopRunning();
                    } else {
                        String messageIn = event.getActionCommand();
                        if (messageIn == null) { // End of Stream;
                            stopRunning();
                        } else { // hey, we can do what we were meant for
                            logger.debug("Request received from client");

                            // doing stuff here
                            ...
                            // done doing stuff

                            logger.debug("Sending Client Response");

                            try {
                                sendResponse(opResponse, out);
                            } catch (Exception ex) {
                                logger.error("Error sending response to OP.", ex);
                            }
                        }
                    }
                }
            }
        });
        listener.start();

        while (shouldContinue) {
            // loop here until shouldContinue = false;
            // this should be set to false in the ActionListener above
        }

        heartbeat.setShouldStop(true);
        return;
    } catch (Exception ex) {
        logger.error("Error in ESPSocketServer", ex);
        return;
    }

}

private void stopRunning() {
    shouldContinue = false;
}

private void sendResponse(ClientResponse opResponse, BufferedOutputStream out) throws Exception {
    logger.debug("Before write");
    out.write(opResponse.getResponse().getBytes());
    logger.debug("After write. Before flush");
    out.flush();
    logger.debug("After flush");
    // this log message is in my logs, so I know the message was sent
}
}

我的StreamListener类。

public class StreamListener extends Thread {
protected final static Logger logger = LogManager.getLogger(StreamListener.class);

public final static String ERROR = "ERROR";

private BufferedReader reader = null;
private List<ActionListener> actionListeners = new ArrayList<>();
private boolean shouldContinue = true;

public StreamListener(BufferedReader reader) {
    this.reader = reader;
}

@Override
public void run() {
    while (shouldContinue) {
        String message;
        try {
            // client blocks here and never receives message
            message = reader.readLine();
            ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, message);
            fireActionPerformed(event);
        } catch (IOException e) {
            e.printStackTrace();
            ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, ERROR);
            fireActionPerformed(event);
        }
    }
}

public void setShouldContinue(boolean shouldContinue) {
    this.shouldContinue = shouldContinue;
}

public boolean getShouldContinue() {
    return shouldContinue;
}

public boolean addActionListener(ActionListener listener) {
    return actionListeners.add(listener);
}

public boolean removeActionListener(ActionListener listener) {
    return actionListeners.remove(listener);
}

private void fireActionPerformed(ActionEvent event) {
    for (ActionListener listener : actionListeners) {
        listener.actionPerformed(event);
    }
}
}

My Heartbeat课程

public class Heartbeat extends Thread {
private BufferedOutputStream bos = null;
private int beatDelayMS = 0;
private String message = null;
private boolean shouldStop = false;

public Heartbeat(int beatDelayMS, String message) {
    this.beatDelayMS = beatDelayMS;
    this.message = message;
    setDaemon(true);
}

@Override
public void run() {
    if (bos == null) { return; }

    while(!shouldStop) {
        try {
            sleep(beatDelayMS);
            try {
                bos.write(message.getBytes());
                bos.flush();
            } catch (IOException ex) {
            //  fall thru
            }
        } catch (InterruptedException ex) {
            if (shouldStop) {
                return;
            }
        }
    }
}

public void setBufferedOutputStream(BufferedOutputStream bos) {
    this.bos = bos;
}

public BufferedOutputStream getBufferedOutputStream() {
    return bos;
}

public void setShouldStop(boolean shouldStop) {
    this.shouldStop = shouldStop;
}

public boolean getShouldStop() {
    return shouldStop;
}
}

My HeartbeatBufferedOutputStream

public class HeartbeatBufferedOutputStream extends BufferedOutputStream {
private Heartbeat heartbeat = null;

public HeartbeatBufferedOutputStream(OutputStream out, Heartbeat heartbeat) {
    super(out);
    this.heartbeat = heartbeat;
    this.heartbeat.setBufferedOutputStream(this);
    heartbeat.start();
}

@Override
public synchronized void flush() throws IOException {
    super.flush();
    heartbeat.interrupt();
}
}

最后这是&#34;客户&#34;类

public class Mockup extends Thread {
protected final static Logger logger = LogManager.getLogger(Mockup.class);

// because we are using threads, we must make this volatile, or the class will
// never exit.
private volatile boolean shouldContinue = true;

public static void main(String[] args) {
    new Mockup().start();
}

@Override
public void run() {
    try (Socket socket = new Socket("localhost", 16100);
            BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));) {

        final StreamListener listener = new StreamListener(in);
        listener.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                if (event.getID() == ActionEvent.ACTION_PERFORMED) {
                    if (event.getActionCommand().equals(StreamListener.ERROR)) {
                        logger.error("Problem listening to stream.");
                        listener.setShouldContinue(false);
                        stopRunning();
                    } else {
                        String messageIn = event.getActionCommand();
                        if (messageIn == null) { // End of Stream;
                            stopRunning();
                        } else { // hey, we can do what we were meant for
                            // convert the messageIn to an OrderPower request, this parses the information
                            logger.info("Received message from server. [" + messageIn + "].");
                        }
                    }
                }
            }
        });
        listener.start();

        StringBuffer buff = new StringBuffer("Some message to send to server");

        logger.info("Sending message to server [" + buff.toString() + "]");
        out.write(buff.toString().getBytes());

        out.flush();

        boolean started = false;
        while (shouldContinue) {
            if (!started) {
                logger.debug("In loop");
                started = true;
            }
            // loop here until shouldContinue = false;
            // this should be set to false in the ActionListener above
        }

        logger.info("Exiting Mockup");

        return;
    } catch (Exception ex) {
        logger.error("Error running MockupRunner", ex);
    }
}

private void stopRunning() {
    shouldContinue = false;
}
}

我已从日志消息中确认服务器向BufferedOutputStream发送消息并刷新,但客户端日志表明它已在reader.readLine()上被阻止,并且永远不会收到消息。

1 个答案:

答案 0 :(得分:1)

你正在读行,但你永远不会写行。在您发送的内容中添加行终止符。