简体   繁体   中英

Java: Cannot write to socket after socket in.readLine()

I am turning to you StackOverflow, I have been butting my head against the wall on this one.

I am doing a little socket programming and I can see when I put the out.println("...") line of code BEFORE the while loop (the in.readLine()) it works correctly, but I need it to be inside the loop.

To be clear, I do not see any errors. I just don't see the text appear on the client-side of this application. It looks as if it is working, but it is not. Also, I do not control the client-side of this either, it is handled by a device that connects via TCP to this Socket Listener application. It it possible that it severs the connection as soon as the data is read?

public class ConnectionHandlerTCP implements Runnable
{
        private final Socket clientSocket;

        ConnectionHandlerTCP(Socket socket)
        {
                clientSocket = socket;
        }

        public void run()
        {
                int uniqueId = 0;
                try (
                        BufferedReader in = new BufferedReader( new InputStreamReader(clientSocket.getInputStream()));
                        PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
                ){
                        String inputLine;

                        // This Line WORKS, I see it appear on the other side of the connection.
                        Log.debug("Sending now A");
                        out.println("text to send here");

                        while ((inputLine = in.readLine()) != null)
                        {
                                // This Line DOES NOT WORK, I do not see it on the other side of the connection.
                                //Log.debug("Sending now B");
                                //out.println("text to send here");

                                // ... bunch of commented out code here
                        }

                        in.close();
                        out.close();
                        clientSocket.close();
                } catch (IOException e) {
                        Log.error("Exception caught when trying to read input.", e.getMessage());
                } catch (Exception e) {
                        Log.error("Exception caught when trying to parse data.", e.getMessage());
                }
        }
}

Any help would be greatly appreciated. In case it is helpful, here is the main class.

import java.net.*;
import java.io.*;

public class SocketListenerTCP 
{
    public static void main(String[] args) throws IOException {

        if (args.length != 1) {
            System.exit(1);
        }

        int portNumber = Integer.parseInt(args[0]);

        while(true)
        {
            try ( 
                ServerSocket serverSocket = new ServerSocket(portNumber);
            ) {

                Socket clientSocket = serverSocket.accept();

                new Thread(new ConnectionHandlerTCP(clientSocket)).start();

            } catch (IOException e) {
                Log.error("Exception caught", e.getMessage());
            }
        }
    }
}

I simplified it a little more, took out the loop completely and this is still not working correctly.

                inputLine = in.readLine();
                Log.debug(inputLine);  

                Log.debug("Sending now");
                out.println("text to send here");

The code inside

while ((inputLine = in.readLine()) != null)

is most likely not running because in.readLine keeps on waiting for an input from the client.

The client program/socket needs to have it's on PrintWriter and println something so that your while loop can read it and respond (assuming that's what you're intending to achieve).

Well, I think I finally figured out the crux of my issue. First off to explain my original problem. I am convinced now that the device I am connecting to disconnects from my server application after 20 seconds (or so) of no activity being read/written. So readline() will wait for that 20s to be up, then returns whatever it has, and there is no writing back to the device allowed at that time. However, if I read all the characters one at a time (via read()), it works just fine, allows me to read the whole message and waits on the last character read iteration of the read() loop for the final "-1" to come through, signaling the end of payload. Between that time (reading the first character and the waiting for the last character), I parse the payload and send anything I want to the device. Which for the most part it receives.

My secondary problem was that sometimes the output streams would appear to be disconnected and never let me send any messages anymore. In the original code, I made the class implement "Runnable". This was a mistake. I saw all over the place that using Runnable was the preferred way to do it, but I noticed that the OutputStream would rarely work in this case, I switched over to extending the Thread class and it works nearly 100% of the time. I believe the one thread was over-writing the output stream of the other, then the next thread doing the same thing and then each of the threads was unable to communicate through the output stream.

After looking at some other examples online, I am assuming there is some way that I could use Runnable if I wanted to, but would have to refactor some other items in my application. I'll have to do some more reading before I go back down that road.

In any case, it seems to be running smoothly for the time being and only rarely fails now. I would still love to know why it still fails on occasion, so I will continue to look into that as time permits.

I am a little baffled still by one of the commenters saying that I couldn't read and write on the same thread...that seems to be completely untrue and reading and writing seems to work just fine, so long as a I read() first (as opposed to readLine()) before I write to the device.

Reading the InputStream of a socket connection is thread blocking. You can not read and write at the same time within the same thread. Move the Printwriter in another thread and you should be fine.

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