/* * Created by Andrey Cherkashin (acherkashin) * http://acherkashin.me * * License * Copyright (c) 2015 Andrey Cherkashin * The project released under the MIT license: http://opensource.org/licenses/MIT */ package ragefist.core.network; import com.juniform.IJUniformPacker; import com.juniform.JUniform; import com.juniform.JUniformObject; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author acherkashin */ public class Client extends SocketClient { private final SocketChannel _socketChannel; private boolean _isConnected; private IJUniformPacker _packer; private ISocketStrategy _socketStrategy; // ---------------------------------------------------------------------- // // STATIC // ---------------------------------------------------------------------- // public static Client newInstance() { try { return new Client(); } catch (IOException ex) { Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); return null; } } // ---------------------------------------------------------------------- // // PUBLIC // ---------------------------------------------------------------------- // @Override public int getPacketBufferSize() { return 4096; } public final void setPacketPacker(IJUniformPacker packer) { _packer = packer; } public boolean connect(InetSocketAddress address) { _isConnected = false; try { _socketChannel.connect(address); while(!_socketChannel.finishConnect()) { Thread.sleep(1); } _isConnected = true; } catch (IOException | InterruptedException ex) { Logger.getLogger(Client.class.getName()).log(Level.SEVERE, "Failed to connect to" + address, ex); } return _isConnected; } @Override public void sendPacket(byte[] bytes) { try { _socketStrategy.writePacket(this, bytes); } catch(IOException ex) { Logger.getLogger(Client.class.getName()).log(Level.WARNING, "Failed to write request into client socket", ex); } } @Override public void sendPacket(JUniformObject packet) { byte[] bytes = _packer.fromUniformObjectToByteArray(packet); sendPacket(bytes); } /** * Returns an array of new packets or NULL if there are no new packets * @param readBuffer * @return array | null * @throws IOException */ @Override public JUniformObject[] readPackets(ByteBuffer readBuffer) throws IOException { byte[][] packets = _socketStrategy.readPackets(this, readBuffer); if (packets.length == 0) { return null; } JUniformObject[] objects = new JUniformObject[packets.length]; for(int i = 0; i < packets.length; i++) { objects[i] = _packer.toUniformObjectFromBytes(packets[i]); } return objects; } @Override public int write(ByteBuffer buffer) { int bytesWritten = 0; try { while(buffer.hasRemaining()) { bytesWritten += _socketChannel.write(buffer); } } catch (IOException ex) { Logger.getLogger(Client.class.getName()).log(Level.SEVERE, "Failed to write into buffer. Closing connection...", ex); close(); } return bytesWritten; } @Override public int read(ByteBuffer buffer) { int bytesSumRead = 0; try { int bytesRead = 0; while((bytesRead = _socketChannel.read(buffer)) > 0) { bytesSumRead += bytesRead; } } catch (IOException ex) { Logger.getLogger(Client.class.getName()).log(Level.SEVERE, "Failed to read from client socket. Closing connection...", ex); close(); } return bytesSumRead; } public void close() { _isConnected = false; try { _socketChannel.close(); } catch (IOException ex) { Logger.getLogger(Client.class.getName()).log(Level.SEVERE, "Failed to close client socket correctly", ex); } } // ---------------------------------------------------------------------- // // PRIVATE // ---------------------------------------------------------------------- // private Client() throws IOException { _socketChannel = SocketChannel.open(); _socketChannel.configureBlocking(false); _packer = JUniform.getPackerInstance(JUniform.PACKER_TYPE_JSON); _socketStrategy = SocketStrategyDefault.getInstance(); } }