简体   繁体   中英

Server: Socket hangs within unpredictable period time at read stream function

I wrote a Java socket server which will keep connection alive until client disconnected. And my client code will keep pushing message to this server app.

But when I run those programs a while, I also seem an unusual condition that Server will hangs while reading input stream from client within unpredictable period. It always hang at inData.read(b) because I see it printed "receiving..." on log when this problem occurred"; even I killed my client, server app still hangs right there.

But when I press Ctrl+C at the console which runs server app after this problem occurred, it will continue to work. This is really annoying.

Is there anyway to solve this Unusual problem nicely?

Server Code:

    static ServerSocket server;

    try {
        server = new ServerSocket("1234");
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    Socket socket = null;
    String inIp = null;
    BufferedInputStream inData;
    BufferedOutputStream outData;

    while (true) {
        try {
            synchronized (server) {
                socket = server.accept();
            }
            inIp = String.valueOf(socket.getInetAddress());
            if (Log4j.log.isEnabledFor(Level.INFO)) {
                Log4j.log.info("Incoming connection " + inIp);
            }
            while (true) {
                inData = new BufferedInputStream(socket.getInputStream());
                outData = new BufferedOutputStream(socket.getOutputStream());
                String reply = "Hey";

                byte[] b = new byte[10240];
                String data = "";
                int length;

                if (Log4j.log.isEnabledFor(Level.INFO)) {
                    Log4j.log.info("InetAddr = " + inIp + ", receiving...");
                }


                // read input stream
                length = inData.read(b);
                data += new String(b, 0, length);
                if (Log4j.log.isEnabledFor(Level.INFO)) {
                    Log4j.log.info("Data Length: " + length + ", Received data:  " + data);
                }


                // output result
                outData.write(reply.getBytes());
                outData.flush();
            }
        } catch (Exception e) {
            String tempStr = e.toString();
            Log4j.log.error("Service error during executing: " + tempStr);
        }
    }

Client Code:

    Socket client = new Socket();
    InetSocketAddress isa = new InetSocketAddress("127.0.0.1", "1234");
    String data = "Hi";

    while(true) {
        try {
            if(!client.isConnected())
                client.connect(isa, 30000);

            BufferedOutputStream out = new BufferedOutputStream(client.getOutputStream());
            BufferedInputStream in = new BufferedInputStream(client.getInputStream());

            // send msg
            out.write(data.getBytes());
            out.flush();


            System.out.println("Message sent, receiving return message...");


            // get return msg
            int length;
            byte[] b = new byte[10240];

            // read input stream
            length = in.read(b);
            retMsg = new String(b, 0, length);

            System.out.println("Return Msg: " + retMsg);

            Thread.sleep(60000); 

        } catch (java.io.IOException | InterruptedException e) {
            System.out.println("Socket Error!");
            System.out.println("IOException :" + e.toString());
        }
    }
try {
    server = new ServerSocket("1234");
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

Don't write code like this. The catch block should be at the end, and all the code that depends on the success of new ServerSocket should be inside the try block.

synchronized (server) {
    socket = server.accept();
}

Synchronization is not necessary here.

while (true) {
    inData = new BufferedInputStream(socket.getInputStream());
    outData = new BufferedOutputStream(socket.getOutputStream());

A large part of the problem, if not all of it, is here. You keep creating new buffered streams, every time around this loop, which means that anything the previous streams have buffered is thrown away. So you are losing input. You should create both these streams before the loop.

while(true) {
    try {
        if(!client.isConnected())
            client.connect(isa, 30000);

This is pointless. Remove. You haven't shown how the client socket was created, but if you created it unconnected you should have connected it before entering this loop.

        BufferedOutputStream out = new BufferedOutputStream(client.getOutputStream());
        BufferedInputStream in = new BufferedInputStream(client.getInputStream());

Here again you must create these streams ahead of the loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM