首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当我从客户端关闭套接字时,socket.getInputSteam.read()不会引发

当我从客户端关闭套接字时,socket.getInputSteam.read()不会引发
EN

Stack Overflow用户
提问于 2011-11-30 22:41:36
回答 1查看 2.2K关注 0票数 0

我在windows 7 x64上。我正在编写一个服务器,它为每个传入的连接打开一个线程--线程从连接的输入流中读取。如果套接字被关闭(),read()应该阻止并抛出异常。它不仅--只是返回- -1。如果我不关闭来自客户端的连接--只是让客户机终止--我会将连接重置为切除--但是如果我关闭()来自客户机的连接(或者只是客户机的输出流),那么服务器线程中的read()就不会抛出--只返回-1文档在这一点上非常清楚:

public ()抛出IOException 关闭这个插座。当前在这个套接字上I/O操作中阻塞的任何线程都会抛出一个SocketException。

帮助

工作代码:

服务器:

代码语言:javascript
运行
复制
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class CloseTest {
    private int port;

    public CloseTest(int port) {
        this.port = port;
    }

    void base_station_activate() {
        ServerSocket baseStationListeningSocket=null;
        try {
            baseStationListeningSocket = new ServerSocket(this.port, 1, InetAddress.getByName("127.0.0.1"));
        } catch (IOException ex) {
        }

        main_server: while (true) {
            try {
                Socket clientSocket = baseStationListeningSocket.accept();
                BaseStationClientHandler ch = new BaseStationClientHandler(clientSocket);
                Thread myThread = new Thread(ch);
                myThread.start();
            } catch (IOException ex) {
                System.exit(1);
            } // main_server
            finally {
//                  baseStationListeningSocket.close()
            }
        }
    }
    public static void main(String args[]){
            CloseTest bs = new CloseTest(8082);
            bs.base_station_activate();
        }
    public class BaseStationClientHandler implements Runnable {
        private final Socket clientSocket;

        private BaseStationClientHandler(Socket clientSocket) {
            this.clientSocket = clientSocket;
        }

        public void run() {
            String debug_message = null;
            try {
                InputStream in = clientSocket.getInputStream();
                // read message and respond
                String s = "";
                char x;
                int r;
                server: while (true) {
                    try {
                        while ((r = in.read()) != (int) '%') {
                            if (r == -1) {
                                debug_message = "Stream/socket .closed() - exception not thrown (WHYYYYY ????) by client";
                                System.out.println(debug_message);
                                break server;
                            }
                            x = (char) r;
                            s += x;
                        }
                        System.out.println(s);
                    } catch (SocketException socketException) {
                        System.out.println(socketException.getLocalizedMessage());  //  if connection reset (but not if Stream/socket .closed()) read throws !!!!!
                        debug_message = "socket_reset";
                        break server;
                    }
                    s = "";
                }   //server
            } catch (IOException ex) {
                System.out.println("IOexception in client handler - check if thrown by read");
            } finally {
                try {
                    clientSocket.close();
                } catch (IOException ex) {
                }
            }
        }
    }
}

客户:

代码语言:javascript
运行
复制
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Vector;

public class CloseTestClient {

    public CloseTestClient(int port, String ipAddress){
        Vector<Socket> connections = new Vector<Socket>();
        try {
            for(int i=0;i<20;i++){
                Socket connection = new Socket(InetAddress.getByName(ipAddress), port);
                connections.add(connection);
                OutputStream out = connection.getOutputStream();
                out.write( ("CONNECT#"+(i+1)+"#1%").getBytes());
                System.out.println("[CloseTestClient SENT]:"+"CONNECT#"+(i+1)+"#1%");
                Thread.sleep(1000); // to be sure the server threads are blocked in the read()
                // connection.close();  // if I comment this out I see the connection reset message from the server when this main terminates
                // commented it out finally and moved the closing at the end to be sure the server threads are blocked in read()
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        finally{
            // if I comment *for* out I see the "connection_reset" message from the server when this main terminates
            for (Socket c : connections){
                try{
                    c.close();
                }catch(Exception ex){
                }
            }
        }
    }

    public static void main(String args[]){
        System.out.println("CloseTestClient run !");
        new CloseTestClient(8082,"127.0.0.1");
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-11-30 22:51:52

您所指的文档适用于该机器上的线程,而不是远程线程。如果套接字X上有线程A read()'ing,而同一进程的线程B关闭socket X,那么线程A的读调用将引发异常。

当本地机器上的套接字是close ()d时,远程机器可以确定不会有更多的数据通过套接字返回-1 (请参阅InputStream的read()文档)。这是当您显式地关闭客户机上的连接时发生的情况。服务器知道没有更多的数据会来,所以read()很高兴地返回-1。没有异常情况。

我猜想,当您让客户端终止而不调用套接字上的close()时,JVM或OS发送的是TCP,而不是很好地关闭连接(发送TCP )。这将导致对服务器的read()调用引发异常。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8334045

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档