Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java BufferedReader将哪个字符解释为流的结尾?_Java_Multithreading_Sockets_Stream_Bufferedreader - Fatal编程技术网

Java BufferedReader将哪个字符解释为流的结尾?

Java BufferedReader将哪个字符解释为流的结尾?,java,multithreading,sockets,stream,bufferedreader,Java,Multithreading,Sockets,Stream,Bufferedreader,当使用从套接字读取时,它声明readLine方法返回 包含行内容的字符串,不包括任何行终止字符,如果已到达流的结尾,则为null 它怎么知道它已经到达了溪流的尽头?它使用什么字符序列来确定这一点 我想模拟发送相同的字符序列来正确关闭另一个使用管道流的连接 编辑: 这是有问题的代码。从响应来看,似乎没有这样的序列,在PipedOutput流上调用close应该解除对输出流上读线的阻塞。它目前似乎没有这样做,这就是为什么我感到困惑,所以我想它可能是其他地方的一个bug 当inputLine=inco

当使用从套接字读取时,它声明readLine方法返回

包含行内容的字符串,不包括任何行终止字符,如果已到达流的结尾,则为null

它怎么知道它已经到达了溪流的尽头?它使用什么字符序列来确定这一点

我想模拟发送相同的字符序列来正确关闭另一个使用管道流的连接

编辑: 这是有问题的代码。从响应来看,似乎没有这样的序列,在PipedOutput流上调用close应该解除对输出流上读线的阻塞。它目前似乎没有这样做,这就是为什么我感到困惑,所以我想它可能是其他地方的一个bug

当inputLine=incomingEventIn.readLine被阻塞时,incomingEventIn.close行似乎被阻塞。如果inputLine=incomingEventIn.readLine未在另一个线程上执行,则incomingEventIn.close将正常执行。为什么会这样

public class SocketManager {

    private Socket socket = null;
    private PrintWriter out = null;
    private BufferedReader in = null;

    private PipedOutputStream incomingEventOutStream = null;
    private PrintWriter incomingEventOut = null;
    private BufferedReader incomingEventIn = null;
    private PipedOutputStream incomingResponsOutStream = null;
    private PrintWriter incomingResponseOut = null;
    private BufferedReader incomingResponseIn = null;

    private ArrayList<AsteriskLiveComsEventListener> listeners = new ArrayList<AsteriskLiveComsEventListener>();
    private final ExecutorService eventsDispatcherExecutor;

    private String ip;
    private int port;

    private Object socketLock = new Object();

    public SocketManager(String ip, int port) {
        this.ip = ip;
        this.port = port;
        eventsDispatcherExecutor = Executors.newSingleThreadExecutor();
    }

    public void connect() throws UnableToConnectException, AlreadyConnectedException {
        synchronized(socketLock) {
            if (socket != null && !socket.isClosed()) {
                throw (new AlreadyConnectedException());
            }
            try {
                socket = new Socket(ip, port);
                out = new PrintWriter(socket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                incomingEventOutStream = new PipedOutputStream();
                incomingEventIn = new BufferedReader(new InputStreamReader(new PipedInputStream(incomingEventOutStream)));
                incomingEventOut = new PrintWriter(incomingEventOutStream);

                incomingResponsOutStream = new PipedOutputStream();
                incomingResponseIn = new BufferedReader(new InputStreamReader(new PipedInputStream(incomingResponsOutStream)));
                incomingResponseOut = new PrintWriter(incomingResponsOutStream);

            } catch (IOException e) {
                throw (new UnableToConnectException());
            }
            new Thread(new IncomingEventThread()).start();
            new Thread(new SocketThread()).start();
        }
    }

    public void disconnect() throws NotConnectedException {
        disconnect(false);
    }

    private void disconnect(boolean notRequested) throws NotConnectedException {
        synchronized(socketLock) {
            if (!isConnected()) {
                throw (new NotConnectedException());
            }

            try {
                incomingEventIn.close();
            } catch (IOException e2) {}
            // IT NEVER GETS TO HERE!
            incomingEventOut.close();
            try {
                incomingResponseIn.close();
            } catch (IOException e1) {}
            System.out.println("disconnecting");
            incomingResponseOut.close();
            try {
                socket.shutdownInput();
            } catch (IOException e) {}
            try {
                socket.shutdownOutput();
            } catch (IOException e) {}
            try {
                socket.close();
            } catch (IOException e) {}

            if (notRequested) {

                System.out.println("disconnecting event");
                dispatchEvent(new ConnectionLostEvent());
            }
        }
    }

    public boolean isConnected() {
        synchronized(socketLock) {
            return (socket != null && !socket.isClosed());
        }
    }

    public void addEventListener(AsteriskLiveComsEventListener a) {
        synchronized(listeners) {
            listeners.add(a);
        }
    }

    public void removeEventListener(AsteriskLiveComsEventListener a) {
        synchronized(listeners) {
            listeners.remove(a);
        }
    }

    private void dispatchEvent(final AsteriskLiveComsEvent e) {
        synchronized (listeners) {
            synchronized (eventsDispatcherExecutor) {
                eventsDispatcherExecutor.execute(new Runnable()
                {
                    public void run()
                    {
                        for(int i=0; i<listeners.size(); i++) {
                            listeners.get(i).onAsteriskLiveComsEvent(e);
                        }
                    }
                });
            }
        }
    }

    public JSONObject sendRequest(JSONObject request) throws JSONException, NotConnectedException {
        synchronized(socketLock) {
            System.out.println("sending request "+request.toString());
            out.println(request.toString());
            try {
                return new JSONObject(incomingResponseIn.readLine());
            } catch (IOException e) {
                // lets close the connection
                try {
                    disconnect(true);
                } catch (NotConnectedException e1) {}
                throw(new NotConnectedException());
            }
        }
    }

private class SocketThread implements Runnable {

    @Override
    public void run() {
        String inputLine = null;
        try {
            while((inputLine = in.readLine()) != null) {
                // determine if this is a response or event and send to necessary location
                JSONObject lineJSON = new JSONObject(inputLine);
                if (lineJSON.getString("type").equals("response")) {
                    incomingResponseOut.println(inputLine);
                    incomingResponseOut.flush();
                }
                else if (lineJSON.getString("type").equals("event")) {
                    incomingEventOut.println(inputLine);
                    incomingEventOut.flush();
                }
            }

            if (isConnected()) {
                try {
                    disconnect(true);
                } catch (NotConnectedException e) {}
            }
        } catch (IOException e) {
            // try and disconnect (if not already disconnected) and end thread
            if (isConnected()) {
                try {
                    disconnect(true);
                } catch (NotConnectedException e1) {}
            }
        }
    }

}

private class IncomingEventThread implements Runnable {

    @Override
    public void run() {
        String inputLine = null;
        try {
            while((inputLine = incomingEventIn.readLine()) != null) {
                JSONObject lineJSON = new JSONObject(inputLine);
                String eventType = lineJSON.getString("eventType");
                // determine what type of event it is and then fire one that represents it
                if (eventType.equals("channelAdded")) {
                    JSONObject a = lineJSON.getJSONObject("payload");
                    Hashtable<String,Object> data = new Hashtable<String,Object>();
                    Object[] keys = a.keySet().toArray();
                    for(int i=0; i<keys.length; i++) {
                        data.put((String) keys[i], a.get((String) keys[i]));
                    }
                    dispatchEvent(new ChannelAddedEvent(data));
                }
                else if (eventType.equals("channelRemoved")) {
                    dispatchEvent(new ChannelRemovedEvent(lineJSON.getJSONObject("payload").getInt("channelId")));
                }
                else if (eventType.equals("channelsToRoom")) {
                    ArrayList<Integer> data = new ArrayList<Integer>();
                    JSONObject a = lineJSON.getJSONObject("payload");
                    JSONArray ids = a.getJSONArray("channelIds");
                    for(int i=0; i<ids.length(); i++) {
                        data.add(ids.getInt(i));
                    }
                    dispatchEvent(new ChannelsToRoomEvent(data));
                }
                else if (eventType.equals("channelToHolding")) {
                    dispatchEvent(new ChannelToHoldingEvent(lineJSON.getJSONObject("payload").getInt("channelId")));
                }
                else if (eventType.equals("channelVerified")) {
                    dispatchEvent(new ChannelVerifiedEvent(lineJSON.getJSONObject("payload").getInt("channelId")));
                }
                else if (eventType.equals("serverResetting")) {
                    dispatchEvent(new ServerResettingEvent());
                }
            }
        } catch (IOException e) {}
        System.out.println("here");
    }

}
编辑2: 我认为这在某种程度上是一个死锁问题,因为如果我在调试器中将一些断点放在它之前,它就会正常运行,inputLine=incomingEventIn.readLine返回null。如果我试着正常运行它,它就会锁定

编辑3:多亏了。输入流在导致锁定的输出之前关闭。它需要另一种方式。首先关闭输出流,然后通知输入流该流已关闭并取消阻止readLine方法。

检查此问题:

它怎么知道它已经到达了溪流的尽头?它使用什么字符序列来确定这一点

答案取决于操作系统,但我熟悉的操作系统不读取EOF字符。操作系统向底层调用方返回指示流文件描述符已达到EOF的返回值。JVM看到返回值并返回相应的返回null,-1。。。发送到InputStream或读取器调用程序,具体取决于方法

我想模拟发送相同的字符序列来正确关闭另一个使用管道流的连接

如果您正在从PipedWriter读取,则关闭关联的PipedWriter。读取器或InputStream随后将向调用者返回适当的EOF值

编辑:

由于您的IncomingEventThread正在读取incomingEventIn,因此disconnect方法应首先关闭incomingEventOut。螺纹应封闭其内侧。然后,您应该关闭响应


我不会让线程调用断开连接。。。。它应该只关闭它的读写器,而不是所有的流。

从您的角度来看,只需在用于连接到测试的PipedOutputStream上调用close

套接字的实际关闭由客户端和服务器上的TCP堆栈执行

这应该注意,您不能在同一线程上读/写管道流,因此有2个方法和一个线程创建:

void runTest ( final PipedInputStream sink ) throws Exception
{
    try( final PipedOutputStream stream = new PipedOutputStream( sink ) )
    {
        try ( final OutputStreamWriter swriter = 
              new OutputStreamWriter( stream, "UTF-8" )
        )
        {
            try ( final PrintWriter writer = new PrintWriter( swriter ) )
            {
                writer.println( "Hello" );

                writer.println( "World!" );
            }
        }
    }
}

void test ( final PipedInputStream sink ) throws InterruptedException
{
    final Thread outputThread =
        new Thread(
            new Runnable ( )
            {
                @Override
                public void run ( )
                {
                    try
                    {
                        runTest( sink );
                    }
                    catch ( final Exception ex )
                    {
                        throw new RuntimeException( ex );
                    }
                }

            }
        );

    outputThread.start( );

    outputThread.join( );
}

没有。操作系统通过文件大小、TCP FIN位或其他带外机制(取决于源)知道流何时到达其末端。我所知道的唯一例外是,终端驱动程序在通过键盘键入时会将Ctrl/d或Ctrl/z识别为EOF,但这同样是操作系统,而不是Java流或读卡器。

在我的pipedreader上调用close似乎不会使readLine返回null并触发解除阻塞。应该吗?“现在它似乎什么也不等了。”汤姆。您应该真正提供您已经拥有的代码。关闭读取器将导致IOException。关闭编写器以读取EOF。我现在已经添加了代码。起初我并不认为这是相关的,我仍然不确定,因为我认为这是我在某处犯的一个编码错误。目前我正在调用PipedReader上的close,readLine似乎仍然没有返回null。我想我在什么地方犯了个错误。谢谢。你打电话给我相信的writer@TomJenkinson@OS不会“关闭输入流”。它通过返回值告诉读者EOS已经发生。应用程序必须关闭流。如果操作系统关闭流,您将永远不会看到“太多打开的文件”。但在我的代码中,当我调用incomingEventIn.close时,incomingEventIn.readLine在另一个线程中似乎没有返回null,并且incomingEventIn.close似乎正在阻塞。我不知道为什么。我已经更新了我的答案。主线程应该关闭2个流,线程应该关闭每个流的另一侧@TomJenkinson。永远不要忽略异常,永远不要用自己的消息替换异常中的消息。请修复代码以记录所有异常并重新运行。你可能会得到一个惊喜。注意:为什么每个插座都有两个螺纹和四个管道?这是
伊姆斯的设计出奇地过于复杂。在Java的16年中,我只使用过一次管道,为了排队,我匆忙地将它们删除了。那里只有2个管道,不是吗?这是我唯一能想到的将从套接字读取的输入拆分,并根据json中声明的类型以两种不同的方式发送它的方法。如果有更好的办法,请告诉我?我知道忽略异常是个坏主意,但如果在这些地方有异常,我真的不知道该怎么办,因为目标是无论如何关闭套接字。两个管道,四个流,加上套接字输入和输出流,每个套接字总共六个。你肯定不需要这些吗?我不关心您如何编写代码,但是如果您在这里展示忽略异常的代码,那么很可能您刚刚错过了抛出的异常。消除这种可能性是你们义不容辞的责任。