Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.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 从套接字多次打开读/写流_Java_Sockets - Fatal编程技术网

Java 从套接字多次打开读/写流

Java 从套接字多次打开读/写流,java,sockets,Java,Sockets,在我有ServerSocket监听传入连接的类中,下面是代码: while(isRunning) { try { Socket s = mysocketserver.accept(); acknowledgeClient(s); new ClientHandler(s).start(); //Start new thread to serve the client, and get back to accept new connec

在我有
ServerSocket
监听传入连接的类中,下面是代码:

while(isRunning)
{
    try
    {
        Socket s = mysocketserver.accept();
        acknowledgeClient(s);
        new ClientHandler(s).start(); //Start new thread to serve the client, and get back to accept new connections.
    }
    catch(Exception ex)
    {
        ex.printStackTrace();
    }
}
下面是
acknowledgeClient(sockets)
code

ObjectInputStream in = new ObjectInputStream(s.getInputStream);
ObjectOutputStream out = new ObjectOutputStream(s.getOutStream);
String msg = in.readObject().toString();
System.out.println(msg+" is Connected"); //Show who's connected
out.writeObject("success"); //Respond with success.
in.close();
out.close();
ClientHandler的
run()
方法

try
{
    in = new ObjectInputStream(client.getInputStream());
    out = new ObjectOutputstream(client.getOutputStream());
    String msg = "";
    while(!msg.equalsIgnoreCase("bye"))
    {
        msg = in.readObject().toString();
        System.out.println("Client Says - "+msg);
        out.writeObject("success");
    }
    in.close();
    out.close();
}
catch(Exception ex)
{
    ex.printStackTrace();
}
下面是客户端程序如何与Echo服务器通信的方式

try
{
    int count = 10;
    client = new Socket("localhost",8666);
    in = new ObjectInputStream(client.getInputStream());
    out = new ObjectOutputstream(client.getOutputStream());
    out.writeObject("Foo");
    System.out.println("Connection Status : "+in.readObject().toString());
    while(count>0)
    {
        out.writeObject("Hello!");
        String resp = in.readObject().toString(); //Getting EOFException here.
        System.out.println("Sent with :"+resp);
        count--;
        Thread.sleep(1000);
    }
    out.close();
    in.close();
    client.close();
}
catch(Exception ex)
{
    ex.printStackTrace();
}
您可能已经注意到,在连接后确认客户端后,我关闭读/写流,从为客户端提供服务的新线程开始,我再次打开流,从服务器开始从连接的套接字读/写,但只要我尝试读取发送时服务器的响应
Hello
通过客户端,它会以
EOFEException
崩溃,而不是获得
成功

我知道EOF发生的原因,但不知道为什么会发生在这里,我不会尝试读取流中没有任何内容的套接字(它应该有服务器编写的
成功

在服务器打印出
Hello之前,客户端试图读取套接字是否为时过早在其末尾并作为响应写入
成功

p.S.:我知道放这么多代码问问题不是一个好方法,我们希望在这里得到问题的答案并理解它,而不是让别人解决我们的问题然后逃之夭夭。因此,我提供了这么多代码来显示问题的各个方面。

我再次打开流,从服务器开始从连接的套接字读/写

一旦流关闭,就不能再打开它。事实上,您根本不能以这种方式在同一个流上使用两个对象流


相反,您应该为输入和输出创建一个对象流,并且只创建一次,并且在完成之前不要关闭它。

我研究了ObjectInputStream的源代码,似乎对原始输入流的引用
s.getInputStream()
存储在ObjectInputStream中

关闭ObjectInputStream时,
s.getInputStream()
也将关闭

输入流一旦关闭,就无法再次打开。因此,您会得到一个EOFEException,它指示您处于流的末尾(因为流无法再次打开)

您应该这样做来确认客户

在ClientHandler的run()方法中:

try {
    // acknowledge client
    ObjectInputStream in = new ObjectInputStream(s.getInputStream());
    ObjectOutputStream out = new ObjectOutputStream(s.getOutStream());
    String msg = in.readObject().toString();
    System.out.println(msg+" is Connected"); //Show who's connected
    out.writeObject("success"); //Respond with success.
    // end acknowledge client

    String msg = "";
    while(!msg.equalsIgnoreCase("bye"))
    {
        msg = in.readObject().toString();
        System.out.println("Client Says - "+msg);
        out.writeObject("success");
    }
    in.close();
    out.close();
}
catch(Exception ex)
{
    ex.printStackTrace();
}

如果您想用单独的方法隔离确认代码,只需确保在不关闭流的情况下维护对同一ObjectInputStream的正确引用,然后传递引用。

好吧,看看这个程序,我编写它是为了理解多个客户端和服务器通信,你的问题在这个节目中得到了回答

客户端代码

public class ClientWala {

    public static void main(String[] args) throws Exception{

        Boolean b = true;
    Socket s = new Socket("127.0.0.1", 4444);

    System.out.println("connected: "+s.isConnected());


    OutputStream output = s.getOutputStream();
    PrintWriter pw = new PrintWriter(output,true);

    // to write data to server
    while(b){

        if (!b){

             System.exit(0);
        }

        else {
            pw.write(new Scanner(System.in).nextLine());
        }
    }


    // to read data from server
    InputStream input   = s.getInputStream();
    InputStreamReader isr = new InputStreamReader(input);
    BufferedReader br = new BufferedReader(isr);
    String data = null;

    while ((data = br.readLine())!=null){

        // Print it using sysout, or do whatever you want with the incoming data from server

    }




    }
}
服务器端代码

public class ServerTest {

    ServerSocket s;

    public void go() {

        try {
            s = new ServerSocket(44457);

            while (true) {

                Socket incoming = s.accept();
                Thread t = new Thread(new MyCon(incoming));
                t.start();
            }
        } catch (IOException e) {

            e.printStackTrace();
        }

    }

    class MyCon implements Runnable {

        Socket incoming;

        public MyCon(Socket incoming) {

            this.incoming = incoming;
        }

        @Override
        public void run() {

            try {
                PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
                        true);
                InputStreamReader isr = new InputStreamReader(
                        incoming.getInputStream());
                BufferedReader br = new BufferedReader(isr);
                String inp = null;

                boolean isDone = true;

                System.out.println("TYPE : BYE");
                System.out.println();
                while (isDone && ((inp = br.readLine()) != null)) {

                    System.out.println(inp);
                    if (inp.trim().equals("BYE")) {
                        System.out
                                .println("THANKS FOR CONNECTING...Bye for now");
                        isDone = false;
                        s.close();
                    }

                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                try {
                    s.close();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }

        }

    }

    public static void main(String[] args) {

        new ServerTest().go();

    }

}

关闭套接字流周围的任何输入流或输出流或读写器将关闭套接字,并暗示关闭其他流、读写器和写器


在套接字的生命周期中使用相同的流、读卡器和写卡器。

所以我根本不能使用main类的
acknowledgeClient()
?Socket的所有IO任务都是从
ClientHandler
的线程中完成的吗?不是您编写它的方式。您可以在调用方法之前创建流,并将其传递给处理程序。通常,处理程序也会进行确认。否则,速度较慢的使用者可能会停止服务器接受任何新连接。请执行相同操作,谢谢…:-)我以为一旦调用了Socket的
close()
,您就可以重新打开它,但我不知道它甚至适用于Socket流。这对我来说也是新的知识。多亏了你的问题,我在研究源代码时发现了这一点:)