简体   繁体   English

Java:socket in.readLine()之后无法写入套接字

[英]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. 我正在向您求助StackOverflow,我一直把头撞在墙上。

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. 我正在做一些套接字编程,我可以看到当我在while循环(in.readLine())之前放入out.println(“ ...”)代码行时,它可以正常工作,但是我需要在循环内。

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. 另外,我也不控制它的客户端,它是由通过TCP连接到此Socket Listener应用程序的设备处理的。 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. 很可能没有运行,因为in.readLine一直在等待客户端的输入。

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). 客户端程序/套接字需要将其放在PrintWriterprintln ,以便您的while循环可以读取它并做出响应(假设这就是您要实现的目标)。

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. 现在,我确信要连接的设备在20秒钟(或大约20秒钟)没有任何活动被读取/写入后,会从服务器应用程序断开连接。 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. 因此,readline()将等待20秒钟,然后返回它所拥有的所有内容,并且此时没有写回该设备的信息。 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. 但是,如果我一次读取所有字符(通过read()),它就可以正常工作,允许我读取整个消息,并等待read()循环的最后一个字符读取迭代以获取最后的“- 1英寸通过,表示有效载荷已结束。 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". 在原始代码中,我使该类实现为“ 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. 我到处都看到使用Runnable是执行此操作的首选方法,但是我注意到OutputStream在这种情况下几乎无法工作,我转而扩展Thread类,并且它在几乎100%的时间内都有效。 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. 在网上查看了其他一些示例之后,我假设可以通过某种方式使用Runnable,但必须在应用程序中重构其他项目。 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. 我仍然对其中一位评论者感到困惑,他们说我不能在同一线程上读写...这似乎是完全不正确的,只要我读了,读写似乎就可以了。 )首先(与readLine()相反),然后再写入设备。

Reading the InputStream of a socket connection is thread blocking. 读取套接字连接的InputStream是线程阻塞。 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. 将Printwriter移到另一个线程中,就可以了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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