Начиная с версии 1.4 в j2se появился package java.nio, который позволяет работать с сокетами в неблокирующем режиме, что зачастую повышает производительность, упрощает код и даёт дополнительные возможности и функционал. А начиная с версии j2se 1.6 на серверах под упралением ОС линукс(kernel 2.6) реализация класса Selector выполнена с использованием epoll, что обеспечивает максимально возможную производительность.
В примере описанном ниже я постараюсь продемонстрироватьь основные принципе работы с неблокирующими сокетами, на примере вполне реальной задачи – реализации Socks 4 прокси сервер.
Во время жизни с неблокирующим сокетом может приключиться всякое, а именно
- OP_ACCEPT – входящее соединение
- OP_READ – на соске данные или дисконнект
- OP_WRITE – соска готова к записи или дисконнект
- OP_CONNECT – соединение или установлено или нет
- select() – блокирующий метод, просыпается по событию или по wakeUp()
- select(long) – та же тема только с таймаутом
- selectNow() – ну и неблокирующий вариант
В нашем случае прокся штука пассивная, поэтому нам больше подходит базовый блокирующий select().
Fix Minecraft Connection Lost — Internal Exception : java.net SocketException: Connection reset Fix
После этого нужно запросить у селектора ключи которые проявили активность за последнюю выборку и используя методы isAcceptable(), isReadable(), isWriteable(), isConnectable() узнать что с ними произошло.
- Принимаем соединение
- Парсим заголовок (для упрощения этого шага мы предполагаем что размер заголовка всегда меньше размера буфера)
- Устанавливаем соединение с целью
- Отвечаем клиенту что всё ОК
- Проксируем
- Закрываем соединения
Чтобы избежать проблем с полными сокет буферами проксировать будем следующим образом:
Пусть у нас два конца A и B при этом A.in=B.out и наоборот, следовательно A.interestOps()|OP_READ!= B.interestOps()|OP_WRITE (чтобы один буфер одновременно не использовался двумя каналами).
После того как одна из сторон закроет соединение, надо дописать данные из буфера второй стороне и закрыть соединение.
Ну и собственно сам код, функции старался расположить в порядке действий для упрощения понимания алгоритма, комментарии прилагаются.
import java.io.IOException ;
import java.net.InetAddress ;
import java.net.InetSocketAddress ;
import java.net.UnknownHostException ;
import java.nio.ByteBuffer ;
import java.nio.channels.ClosedChannelException ;
import java.nio.channels.SelectionKey ;
import java.nio.channels.Selector ;
import java.nio.channels.ServerSocketChannel ;
import java.nio.channels.SocketChannel ;
import java.nio.channels.spi.SelectorProvider ;
import java.util.Iterator ;
ByteBuffer in ;
/**
* Буфер для записи, в момент проксирования равен буферу для чтения для
* ключа хранимого в peer
*/
ByteBuffer out ;
как исправить internal exception java.io.ioexception удаленный хост
/**
* Куда проксируем
*/
SelectionKey peer ;
/**
* так выглядит ответ ОК или Сервис предоставлен
*/
static final byte [ ] OK = new byte [ ] < 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 >;
> catch ( Exception e ) <
e. printStackTrace ( ) ;
throw new IllegalStateException ( e ) ;
>
>
public static void main ( String [ ] args ) <
Socks4Proxy server = new Socks4Proxy ( ) ;
server. host = «127.0.0.1» ;
server. port = 1080 ;
server. run ( ) ;
>
>
Далее открываем ваш любимый браузер, выбираем socks 4 proxy вводим 127.0.0.1:1080 и проверяем работоспособность.
Источник: habr.com
Вы очень активны! Это здорово!
Netty 4.0 на нескольких портах с несколькими протоколами?
Почему Netty дает мне только 768 байт из сообщений UDP
Выяснение, какие сетевые сокеты открыты в текущей Java VM
Dec 25, 2012, 10:28 AM
Исключение java.nio.channels.ClosedChannelException при записи в канал клиента
Я создал игровой сервер с использованием netty 3.5.8. Во-первых, нет проблем с отправкой данных с сервера на клиент. Но когда сервер работает какое-то время, есть много исключений [ java.nio.channels.ClosedChannelException ] когда я записываю данные в канал клиента.
Любой получил это исключение раньше. Есть ли совет, чтобы это исправить? Я думаю о буфере кеша причина этого.
Пример моего кода такой:
ChannelBuffer bff = ChannelBuffers.buffer(18); bff.writeByte(Events.S_SERVER_PUSH); bff.writeByte((byte)0); bff.writeInt(idRoom); bff.writeInt(playerCnt); bff.writeInt(gameCnt); bff.writeInt(freePlayer); channel.write(bff);
java.nio.channels.ClosedChannelException at org.jboss.netty.channel.socket.nio.AbstractNioWorker.cleanUpWriteBuffer(AbstractNioWorker.java:784) at org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromUserCode(AbstractNioWorker.java:507) at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleAcceptedSocket(NioServerSocketPipelineSink.java:129) at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:66) at org.jboss.netty.channel.Channels.write(Channels.java:733) at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.doEncode(OneToOneEncoder.java:71) at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.handleDownstream(OneToOneEncoder.java:60) at org.jboss.netty.channel.Channels.write(Channels.java:712) at org.jboss.netty.channel.Channels.write(Channels.java:679) at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:248) at myclass.SendPushData(GameRoom.java:231) at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:296) at org.jboss.netty.handler.codec.frame.FrameDecoder.unfoldAndFireMessageReceived(FrameDecoder.java:458) at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:439) at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:303) at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268) at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255) at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:84) at org.jboss.netty.channel.socket.nio.AbstractNioWorker.processSelectedKeys(AbstractNioWorker.java:471) at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:332) at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:35) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source)
Источник: techfeed.net
ClosedChannelException
Checked exception thrown when an attempt is made to invoke or complete an I/O operation upon channel that is closed, or at least closed to that operation. That this exception is thrown does not necessarily imply that the channel is completely closed. A socket channel whose write half has been shut down, for example, may still be open for reading.
Public Constructor Summary
Constructs an instance of this class.
Inherited Method Summary
From class java.lang.Throwable
Appends the specified exception to the exceptions that were suppressed in order to deliver this exception.
Fills in the execution stack trace.
Returns the cause of this throwable or null if the cause is nonexistent or unknown.
Creates a localized description of this throwable.
Returns the detail message string of this throwable.
Provides programmatic access to the stack trace information printed by printStackTrace() .
Returns an array containing all of the exceptions that were suppressed, typically by the try -with-resources statement, in order to deliver this exception.
Initializes the cause of this throwable to the specified value.
Prints this throwable and its backtrace to the standard error stream.
Prints this throwable and its backtrace to the specified print writer.
Prints this throwable and its backtrace to the specified print stream.
setStackTrace (StackTraceElement[] stackTrace)
Sets the stack trace elements that will be returned by getStackTrace() and printed by printStackTrace() and related methods.
Источник: developers.google.com