SocketChannel.read () получил правильные данные только один раз и пусто - PullRequest
0 голосов
/ 18 октября 2018

Чтобы проверить отправку данных с помощью SocketChannel:

Мое Java-приложение использует SocketChannel.write () для повторной отправки одних и тех же данных со случайной короткой задержкой.При проверке журнала cmdline данные всегда отправляются правильно.

|2018|0|null|null|0|....000000|0.000000|
|2018|0|null|null|0|....000000|0.000000|
|2018|0|null|null|0|....000000|0.000000|
|2018|0|null|null|0|....000000|0.000000|
|2018|0|null|null|0|....000000|0.000000|

Приложение My Kotlin получает данные с помощью SocketChannel.read () и немного печатает журналы.С инициализированным SocketChannel mySocketChannel и селектором selector:

while ( true ) {
    selector.select ( )
    val selectedKeys = selector.selectedKeys ( )
    selectedKeys.parallelStream ( )
        .forEach {
            when ( it.channel ( ) ) {
                mySocketChannel -> run {
                    if ( it.isReadable ( ) )
                    {
                        read@ while ( true )
                        {
                            input.position ( 0 )
                            val len = mySocketChannel.read ( input )
                            print ( "len=$len " )
                            when
                            {
                                len > 1 -> {
                                    input.position ( 0 );
                                    val data = ByteArray ( len )
                                    input.get ( data )
                                    println ( Calendar.getInstance ( ).toInstant ( ).toString ( ) + "\t" + data.size )
                                    println ( String ( data ).substring ( 0, 20 ) + "..." + String ( data ).substring ( data.size - 20 ) )
                                }
                                len < -1    -> {
                                    // dead connection
                                    println ( "Dead connection" )
                                    // unregister later
                                    break@read
                                }
                                else    -> {
                                    break@read
                                }
                            } // when: read from server
                        } // while: 1
                    } // if: readable
                }
                else -> { }
            } // when: readable channel
        } // foreach: selected keys
    selectedKeys.clear ( )
} // while: 1

Соединение все еще в порядке, но проблема в том, что полученные данные были верны только в первый раз и становятся пустыми:

len=10000 2018-10-18T17:55:21.606Z      10000
|2018|0|null|null|0|....000000|0.000000|
len=0
len=10000 2018-10-18T17:55:30.119Z      10000
            ...
len=0 
len=10000 2018-10-18T17:55:30.625Z      10000
            ...
len=0 
len=10000 2018-10-18T17:55:31.131Z      10000
            ...
len=0 
len=10000 2018-10-18T17:55:32.136Z      10000
            ...

Итак, что происходит?

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

Я тестировал с приемником Java, и возникла та же проблема.Итак, давайте посмотрим на источник отправителя:

final byte [] cache = ( data + ( data.charAt ( data.length ( ) - 1 ) != '\n' ? "\n" : "" ) ).getBytes ( );

try {
    selector.selectNow ( );
    Set <SelectionKey> selectedKeys = selector.selectedKeys ( );
    selectedKeys.parallelStream ( ).forEach ( selectedKey -> {
        ByteBuffer bb = ByteBuffer.allocate ( cache.length );
        bb.wrap ( cache );
        System.out.print ( new String ( cache ).substring ( 0, 20 ) + "..." + new String ( cache ).substring ( cache.length - 20 ) );
        if ( selectedKey.isWritable ( ) )
        {
            try {
                int len = ( (SocketChannel) selectedKey.channel ( ) ).write ( bb );
            } catch ( IOException ioe ) {
                ioe.printStackTrace ( );
                // dead connection
                try { selectedKey.channel ( ).close ( ); } catch ( IOException ioe1 ) { }
            }
        }
    } );
    selectedKeys.clear ( );
} catch ( IOException ioe ) {
    ioe.printStackTrace ( );
}

1 Ответ

0 голосов
/ 19 октября 2018

Наконец, я обнаружил, что причина:

bb.wrap ( cache );

И решение заключается в замене на:

bb.put ( cache ).flip ( );
...