Получите EOFException после первого SocketTimeoutException - PullRequest
1 голос
/ 15 августа 2011

Это простой TCP-сервер (эхо) и TCP-клиент в Java.

Если я прокомментирую следующую строку, программа работает:

st.setSoTimeout(WAITING_FOR_INPUT);

Но если я использую этометод тайм-аута сокета, тогда я получу сначала InterruptedIOException (это все еще хорошо).Но на следующей итерации я получу EOFException (это проблема).

Я не понимаю, что не так?Пожалуйста, помогите!

CSimpleServer.java

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

public class CSimpleServer
{
    public static final int WAITING_FOR_INPUT = 10; // 10 ms

    public CServerThread st;

    public class CServerThread extends Thread
    {
        ServerSocket ss;
        Socket st;
        ObjectInputStream in;
        ObjectOutputStream out;

        int sleeping_time;
        int port;

        CServerThread(int port, int sleeping_time)
        {   
            st = null;
            in = null;
            out = null;

            this.port = port;
            this.sleeping_time = sleeping_time;
        }

        public void run()
        {
            try {
                ss = new ServerSocket(port);
            }
            catch (IOException ioe) {
                System.err.println("Create server failed: " + ioe.getMessage());
                return;
            }

            try {
                st = ss.accept();
                st.setSoTimeout(WAITING_FOR_INPUT); 
                out = new ObjectOutputStream(st.getOutputStream());
                out.flush();
                in = new ObjectInputStream(st.getInputStream());
            }
            catch (IOException ioe) {
                System.err.println("Catch connection failed: " + ioe.getMessage());
                return;
            }

            while (true) {
                try {
                    int i_data = in.readInt();
                    if (i_data == 0) {
                        break;
                    }
                    System.out.println("Get: " + i_data);
                    out.writeInt(i_data);
                    out.flush();
                    out.reset();

                    sleep(sleeping_time);
                }
                catch (InterruptedIOException ire) {
                    System.out.println("Read data timeout."); // for debug
                    continue;
                }
                catch (EOFException eof) {
                    System.err.println("Reach end of stream: " + eof.getMessage());
                    break;
                }               
                catch (IOException ioe) {
                    System.err.println("Read data failed: " + ioe.getMessage());
                    break;
                }
                catch (InterruptedException ire) {
                    System.err.println("Something interrupted this thread: " + ire.getMessage());
                }
            }

            try {
                in.close();
                out.close();
                st.close();
                ss.close();
            }
            catch (IOException ioe) {
                System.err.println("Close server failed: " + ioe.getMessage());
                return;
            }
        }
    }

    CSimpleServer()
    {
        st = null;
    }

    public static void main(String[] args)
    {
        CSimpleServer prog = new CSimpleServer();

        prog.st = prog.new CServerThread(3800, 1000);
        prog.st.start();
    }
}

CSimpleClient.java

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

public class CSimpleClient
{

    public CClientThread ct;

    public class CClientThread extends Thread
    {
        Socket st;
        ObjectInputStream in;
        ObjectOutputStream out;

        int port;

        CClientThread(int port)
        {   
            st = null;
            in = null;
            out = null;

            this.port = port;
        }

        public void run()
        {
            try {
                st = new Socket(InetAddress.getLocalHost(), port);
                out = new ObjectOutputStream(st.getOutputStream());
                out.flush();
                in = new ObjectInputStream(st.getInputStream());
            }
            catch (UnknownHostException uhe) {
                System.err.println("Unknown server: " + uhe.getMessage());
                return;
            }           
            catch (IOException ioe) {
                System.err.println("Connect to server failed: " + ioe.getMessage());
                return;
            }

            BufferedReader ink = new BufferedReader(new InputStreamReader(System.in));

            while (true) {
                try {

                    String s = ink.readLine();
                    int i_data = Integer.valueOf(s);
                    out.writeInt(i_data);
                    out.flush();
                    out.reset();
                    if (i_data == 0) {
                        ink.close();
                        break;
                    }
                    i_data = in.readInt();
                    System.out.println("Echo: " + i_data);
                }
                catch (IOException ioe) {
                    System.err.println("Send/read data failed: " + ioe.getMessage());
                    break;
                }
            }

            try {
                in.close();
                out.close();
                st.close();
            }
            catch (IOException ioe) {
                System.err.println("Close client failed: " + ioe.getMessage());
                return;
            }
        }
    }

    CSimpleClient()
    {
        ct = null;
    }

    public static void main(String[] args)
    {
        CSimpleClient prog = new CSimpleClient();

        prog.ct = prog.new CClientThread(3800);
        prog.ct.start();
    }
}

Ответы [ 2 ]

0 голосов
/ 16 августа 2011

Если вы получили EOFException, это означает, что одноранговый узел закрыл соединение, двух способов нет.

Я согласен со Сниколасом. 10 мс - нелепо короткий тайм-аут. Установите не менее 5 секунд.

Вы также должны установить время ожидания после , создав ObjectInputStream.

0 голосов
/ 15 августа 2011

Вы пытались увеличить значение тайм-аута, 10 мс - довольно быстрая сеть, в зависимости от контекста ...

Кстати, я люблю давать константы в их именах, код более читабелен.

С уважением, Stéphane

...