Гнездо зеркала отправляет, но не получает - PullRequest
2 голосов
/ 23 декабря 2011

У меня есть программа на Java, которая отражает соединение между клиентским сервером и удаленным сервером.Зеркало отправляет данные, находит, но не получает.Я не могу на всю жизнь понять, почему.Вот мой код:

Socket client = new Socket("127.0.0.1", 42001);
System.out.println("Connected to client!");
Socket server = new Socket(serverAddress, serverPort);
System.out.println("Connected to server!");

BufferedReader clientin = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedWriter scratchout = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));

BufferedReader serverin = new BufferedReader(new InputStreamReader(server.getInputStream()));
BufferedWriter serverout = new BufferedWriter(new OutputStreamWriter(server.getOutputStream()));

int i;
boolean serverNeedsFlush = false;
boolean clientNeedsFlush = false;
while (true)
{
    while (clientin.ready())
    {
        i = clientin.read();
        serverout.write(i);
        serverNeedsFlush = true;
    }
    if(serverNeedsFlush)
    {
        serverout.flush();
        serverNeedsFlush = false;
    }
    while (serverin.ready())
    {
        i = serverin.read();
        System.out.print((char)i);
        scratchout.write(i);
        clientNeedsFlush = true;
    }
    if(clientNeedsFlush)
    {
        scratchout.flush();
        clientNeedsFlush = false;
    }
}

Ответы [ 2 ]

1 голос
/ 24 декабря 2011

Вы не можете сделать это правильно в одной теме. Вам нужны две нити, по одной в каждом направлении. Каждый поток просто читает и пишет, пока не встретит EOS. И не используйте available (): просто заблокируйте чтение. Установите тайм-аут чтения, чтобы избежать патологических ситуаций.

1 голос
/ 23 декабря 2011

Если вы пытаетесь переслать данные из одного сокета в другой, вероятно, было бы лучше использовать потоки сокетов напрямую, а не украшать их.

Как и другие авторы предложили вам использовать темы для этого. Это облегчит жизнь. Затем вы можете использовать потоки, чтобы выполнить базовое копирование в потоковом режиме, как показано ниже.

public static void streamCopy(InputStream in, OutputStream out)
       throws IOException{

        byte[] data = new byte[1024];
        int length;
        do{
            length = in.read(data);
            if(length > 0){
                out.write(data, 0, length);
                out.flush();
            }
        }while(length != -1);

}

Когда вышеприведенный метод вернется, вы прочитаете весь поток in и запишите его в поток out. Ваш метод run для вашего потока или runnable может выглядеть примерно так:

public void run() {

    Socket inSock = null;
    Socket outSock = null;
    try{
        inSock = new Socket(inHost, inPort);
        outSock = new Socket(inHost, inPort);
        /* Set up some socket options here (timeouts, buffers etc)*/

        /* Insert pre copy actions */

        /* This method won't return until inSock's inputStream hits end of stream. 
         * and all the data has been written to outSock's outputStream and flushed. */
        streamCopy(inSock.getInputStream(), outSock.getOutputStream());

        /* In order to really do this correctly you should create an 
         * application protocol that verifies the upstream receiver 
         * is actually getting the data before you close the socket. */

        /* Insert post copy actions */

    }catch(Exception e){
        /* Corrective action or logging here */
    }finally{
        /* Don't forget to close the sockets. */
        if(inSock != null){
            try{
                inSock.close();
            }catch(Exception e){
                /* Don't care */
            }
        }
        if(outSock != null){
            try{
                outSock.close();
            }catch(Exception e){
                /* Don't care */
            }
        }
    }
}
...