Проблема с Socket Streams в коде Java "Telnet"? - PullRequest
0 голосов
/ 22 марта 2012

У меня проблемы с переходом на Java с C / C ++ для моего интерфейса "Telnet" на некоторые модули, с которыми мы здесь работаем.Я хочу установить соединение с картой, которая после запуска интерфейса командной строки ожидает подключения и выдает запрос («OK>») клиентам.Это прекрасно работает как для клиентов C, так и для C #, которые я написал, но Java породил у меня некоторые проблемы.Я приложил некоторый код, который я взял из некоторых примеров в Интернете, но пока все, что я могу точно убедиться, это то, что сокет создается.

Код:

   private boolean CreateTelnetSession()
   {
        try
        {
            _socket = new Socket();
            _socket.connect(new InetSocketAddress(_ipAddr, _ipPort));
            _socket.setSoTimeout(10000);
            _socket.setKeepAlive(true);

            _out = new PrintWriter(_socket.getOutputStream(), true);
            _in = new BufferedReader(new InputStreamReader(_socket.getInputStream()));

            _out.println("\r\n");

            System.out.println(_in.readLine());

            return true;
        }
        catch(Exception e)
        {
            System.out.println("Exception!");
        }
        return false;
    }

сокет SEEMS должен быть создан правильно, и когда программа завершает работу, я вижу закрытие сеанса на карте (ах), с которой пытаюсь разговаривать, но я не вижу возврата каретки / перевода строки, отраженного на картекак и следовало ожидать, или приглашение возвращается через InputStream.Возможно ли, что это проблема кодировки символов?Я делаю что-то неправильно с потоками (пересекая их!?!)?Любое понимание вообще?Когда я преодолею эту начальную кривую обучения, я хотел бы признать, насколько легко Java делает эти сокеты для чтения и записи, но до тех пор ...

Я прочитал этот пост: Java-простой клиент Telnet с использованием сокетов

Это похоже на то, с чем я сталкиваюсь, но это не то же самое.Я готов принять удар, если кто-то видел здесь что-то, что решает мою проблему, так что не стесняйтесь, прямо дайте мне знать, что я пропустил.

Редактировать:

private boolean CreateTelnetSession()
{
    try
    {
        _socket = new Socket();
        _socket.connect(new InetSocketAddress(_ipAddr, _ipPort));
        _socket.setSoTimeout(10000);
        _socket.setKeepAlive(true);

        _out = new DataOutputStream(_socket.getOutputStream());
        _in = new DataInputStream(_socket.getInputStream());

        _outBuffer = ByteBuffer.allocate(2048);
        _outBuffer.order(ByteOrder.LITTLE_ENDIAN);
        _inBuffer = ByteBuffer.allocate(2048);
        _inBuffer.order(ByteOrder.LITTLE_ENDIAN);

        System.out.println("Connection Response: " + _in.read(_inBuffer.array()));
        System.out.println("Response: " + WriteCommand("DRS\r\n"));

        return true;
    }
    catch(Exception e)
    {
        System.out.println("Exception!");
    }
    return false;
}

private String WriteCommand(String command)
{
    try
    {
        _outBuffer = encoder.encode(CharBuffer.wrap(command));
        _out.write(_outBuffer.array());
        _out.flush();

        _in.read(_inBuffer.array());
        String retString = decoder.decode(_inBuffer).toString();

        return retString.substring(0, retString.indexOf('>') + 1);
    }
    catch(Exception e)
    {
        System.out.println("Exception!");
    }

    return "E1>";
}   

Есть много вещей, которые нужно очистить, и я собираюсь поэкспериментировать с тем, нужно ли мне делать это именно таким образом, но это суть "решения".Главным убийцей был порядок байтов.Следует еще раз упомянуть, что это уродливый и непроизводственный код, но любой другой вклад все равно будет оценен.

1 Ответ

1 голос
/ 22 марта 2012

У меня есть пара вещей, которые вы можете попробовать. Вы используете PrintWriter для вывода, это довольно высокоуровневый Writer (то есть он многое из вас инкапсулирует). Меня беспокоит то, что метод println () в PrintWriter добавляет символы конца строки в конце автоматически (в зависимости от вашей ОС). Итак, что вы на самом деле отправляете, это "/ r / n (терминатор строки)", поэтому в окне Unix вы будете отправлять "/r/n/n".

Я бы порекомендовал перейти на DataOutputStream, который дает вам гораздо больший контроль над необработанными байтами, которые отправляются: http://docs.oracle.com/javase/6/docs/api/java/io/DataOutputStream.html

Помните, что если вы переключаетесь на DataOutputStream, вам нужно вызвать flush для выходного потока.

Моя другая мысль - это может быть проблема с порядком байтов. Java строго Big Endian (сетевой порядок байтов). Возможно ли, что ваша «карта» читает вещи в порядке байтов? Если вам нужно писать по сети с прямым порядком байтов (если ваша карта плохая сеть!), Вам нужно будет использовать ByteBuffer, установите его порядок в порядке байтов. Запишите в него свои байты, затем запишите байты из вашего ByteBuffer в DataOutputStream.

Я бы, вероятно, переключился на DataInputStream и для вашего входного потока. readline () вернется только после того, как символ новой строки будет замечен. Ваша карта возвращает новую строку в своем ответе?

Моя последняя мысль: у ваших методов println может быть ошибка, и вы ее не знаете, потому что PrintWriter не генерирует исключения. PrintDriter JavaDocs говорит:

"Методы в этом классе никогда не генерируют исключения ввода-вывода, хотя некоторые из его конструкторов могут. Клиент может узнать, возникли ли какие-либо ошибки, вызвав checkError ()."

Надеюсь, что-то в моем длинном бессвязном ответе поможет вам.

...