Why a key has to be removed from selectedKeys - java

This is a simple server, I used nc as clients to connect to the server, the first client went through and entered the acceptHandler. However, the second client cannot trigger the select to return a number greater than 0 (the return value of select is 0). I see that removing the processed key will resolve the issue, what I don't understand is that why a new connection cannot trigger an event when the serverSocket is still registered with the selector
static ServerSocketChannel server;
static Selector selector;
public static void main(String[] args) throws IOException {
server = ServerSocketChannel.open();
server.bind(new InetSocketAddress(9090));
server.configureBlocking(false);
selector = Selector.open();
server.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
int num;
while ((num = selector.select()) > 0) {
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iter = selectionKeys.iterator();
while (iter.hasNext()) {
SelectionKey sk = iter.next();
// iter.remove();
if (sk.isAcceptable()) {
acceptHandler(sk);
} else if (sk.isReadable()) {
readHandler(sk);
}
}
}
}
}
public static void acceptHandler(SelectionKey sk) {
System.out.println("accept handle");
ServerSocketChannel server = (ServerSocketChannel) sk.channel();
SocketChannel client = null;
try {
client = server.accept(); // return null if no pending connections
if (client != null) {
client.configureBlocking(false);
ByteBuffer buffer = ByteBuffer.allocate(65535);
client.register(selector, SelectionKey.OP_READ, buffer);
}
} catch (IOException e) {
e.printStackTrace();
}
}

Related

Not able to get the output in NIO

I want the program to give me an echo back when i type something, i don't get any errors but it doesn't work, it connects properly but i don't receive anything back when i type in the server
private static Selector selector;
public static void main(String[] args) throws IOException {
selector = Selector.open();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.bind(new InetSocketAddress("localhost", 8080));
ssc.configureBlocking(false);
ssc.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select();
for (Iterator<SelectionKey> it = selector.selectedKeys().iterator(); it.hasNext();) {
SelectionKey key = it.next();
it.remove();
if (key.isAcceptable())
acceptRead(key);
else if (key.isWritable())
write(key);
}
}
}
private static void acceptRead(SelectionKey key) throws IOException {
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel sc = ssc.accept();
System.out.println("Connected with " + sc);
sc.configureBlocking(false);
SelectionKey key2 = sc.register(selector, SelectionKey.OP_WRITE);
ByteBuffer buf = ByteBuffer.allocate(32);
sc.read(buf);
buf.flip();
key2.attach(buf);
}
private static void write(SelectionKey key) throws IOException {
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer buf = (ByteBuffer) key.attachment();
sc.write(buf);
}
}
Very strange code here.
If the key is acceptable you should call accept() on the channel.
If the key is readable you should call read() on the channel.
If you get -1 from read() you must close the channel.
After you write you must compact() the buffer, and surely you want to register the channel for OP_READ again?

DatagramChannel not receiving any bytes on Android

Update
I tried the same implementation, but this time with ServerSocketChannel/SocketChannel. This works on Android. It seems that I am somehow having 100% packet loss over UDP on Android. Does anyone have thoughts on the cause for this? (It is not a WiFi-issue. The UDP client works from my notebook.)
Original
I am having trouble receiving packets in an Android application. The Android application is able to send data to the desktop server, who replies immediately, but always receives zero bytes. The same code works when I use it as a desktop client application.
My Android application has the INTERNET permission. I also tried it with NETWORK, CHANGE_WIFI_MULTICAST_STATE, ACCESS_WIFI_STATE and ACCESS_NETWORK_STATE. That made no difference, sadly.
Tried it both on a device and in an emulator.
Below is the code and a sample of the output.
MainActivity:
private Thread thread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
thread = new Thread(new Client());
thread.start();
}
Client:
public class Client implements Runnable {
private static final String LOG_TAG = "NET";
private static final String IP = "--.---.---.--";
private static final int PORT = 6543;
private final ByteBuffer byteBuffer = ByteBuffer.allocate(256);
private boolean running;
public Client() {
running = false;
}
#Override
public void run() {
try {
final Selector selector = Selector.open();
final DatagramChannel datagramChannel = DatagramChannel.open();
datagramChannel.configureBlocking(false);
datagramChannel.register(selector, SelectionKey.OP_WRITE);
datagramChannel.connect(new InetSocketAddress(IP, PORT));
running = true;
while (running) {
selector.select();
final Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
final SelectionKey key = keys.next();
if (key.isReadable()) {
handleRead(key);
}
if (key.isValid() && key.isWritable()) {
handleWrite(key);
}
keys.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void handleRead(final SelectionKey key) throws IOException {
final DatagramChannel channel = (DatagramChannel) key.channel();
byteBuffer.clear();
final SocketAddress from = channel.receive(byteBuffer);
byteBuffer.flip();
Log.i(LOG_TAG, String.format("Received %d bytes from %s", byteBuffer.limit(), from));
key.interestOps(SelectionKey.OP_WRITE);
}
private void handleWrite(final SelectionKey key) throws IOException {
final DatagramChannel channel = (DatagramChannel) key.channel();
byteBuffer.clear();
byteBuffer.putInt(1234);
byteBuffer.flip();
final SocketAddress to = new InetSocketAddress(IP, PORT);
final int bytes = channel.send(byteBuffer, to);
Log.i(LOG_TAG, String.format("Send %d bytes to %s", bytes, to));
key.interestOps(SelectionKey.OP_READ);
}
}
Server:
public class Server implements Runnable {
private static final int PORT = 6543;
private final ByteBuffer byteBuffer = ByteBuffer.allocate(256);
private SocketAddress from;
private boolean running;
public Server() {
from = null;
running = false;
}
#Override
public void run() {
try {
final Selector selector = Selector.open();
final DatagramChannel datagramChannel = DatagramChannel.open();
datagramChannel.configureBlocking(false);
datagramChannel.socket().setReuseAddress(true);
datagramChannel.register(selector, SelectionKey.OP_READ);
datagramChannel.bind(new InetSocketAddress(PORT));
running = true;
while (running) {
selector.selectNow();
final Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
final SelectionKey key = keys.next();
if (key.isReadable()) {
handleRead(key);
}
if (key.isValid() && key.isWritable()) {
handleWrite(key);
}
keys.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void handleRead(final SelectionKey key) throws IOException {
final DatagramChannel channel = (DatagramChannel) key.channel();
byteBuffer.clear();
from = channel.receive(byteBuffer);
byteBuffer.flip();
System.out.println(String.format("Received %d bytes from %s", byteBuffer.limit(), from));
key.interestOps(SelectionKey.OP_WRITE);
}
private void handleWrite(final SelectionKey key) throws IOException {
final DatagramChannel channel = (DatagramChannel) key.channel();
if (from != null) {
byteBuffer.clear();
byteBuffer.putInt(1234);
byteBuffer.flip();
final int bytes = channel.send(byteBuffer, from);
System.out.println(String.format("Send %d bytes to %s", bytes, from));
}
key.interestOps(SelectionKey.OP_READ);
}
public static void main(String args[]) {
new Thread(new Server()).start();
}
}
Client output:
Send 4 bytes to /--.---.---.--:6543
Received 0 bytes from null
Send 4 bytes to /--.---.---.--:6543
Received 0 bytes from null
Server output:
Received 4 bytes from /--.---.---.--:52974
Send 4 bytes to /--.---.---.--:52974
Received 4 bytes from /--.---.---.--:52974
Send 4 bytes to /--.---.---.--:52974

Connection refused after connecting 75 clients to server

I had developed a server channel socket using below code:
public class EchoServer {
private static final int BUFFER_SIZE = 1024;
private final static int DEFAULT_PORT = 9090;
private long numMessages = 0;
private long loopTime;
private InetAddress hostAddress = null;
private int port;
private Selector selector;
// The buffer into which we'll read data when it's available
private ByteBuffer readBuffer = ByteBuffer.allocate(BUFFER_SIZE);
int timestamp=0;
public EchoServer() throws IOException {
this(DEFAULT_PORT);
}
public EchoServer(int port) throws IOException {
this.port = port;
hostAddress = InetAddress.getByName("127.0.0.1");
selector = initSelector();
loop();
}
private Selector initSelector() throws IOException {
Selector socketSelector = SelectorProvider.provider().openSelector();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
InetSocketAddress isa = new InetSocketAddress(hostAddress, port);
serverChannel.socket().bind(isa);
serverChannel.register(socketSelector, SelectionKey.OP_ACCEPT);
return socketSelector;
}
private void loop() {
for (;true;) {
try {
selector.select();
Iterator<SelectionKey> selectedKeys = selector.selectedKeys()
.iterator();
while (selectedKeys.hasNext()) {
SelectionKey key = selectedKeys.next();
selectedKeys.remove();
if (!key.isValid()) {
continue;
}
// Check what event is available and deal with it
if (key.isAcceptable()) {
accept(key);
} else if (key.isWritable()) {
write(key);
}
}
Thread.sleep(3000);
timestamp+=3;
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}
private void accept(SelectionKey key) throws IOException {
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
socketChannel.setOption(StandardSocketOptions.TCP_NODELAY, true);
// socketChannel.register(selector, SelectionKey.OP_READ);
socketChannel.register(selector, SelectionKey.OP_WRITE);
System.out.println("Client is connected");
}
private void write(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer dummyResponse = ByteBuffer.wrap(("ok:" + String.valueOf(timestamp)) .getBytes("UTF-8"));
socketChannel.write(dummyResponse);
if (dummyResponse.remaining() > 0) {
System.err.print("Filled UP");
}
System.out.println("Message Sent");
// key.interestOps(SelectionKey.OP_READ);
}
}
As you can see I run it on localhost port 9090. In order to testing the code for heavy connections I developed a test app that each second run a new thread and connect to the server. This is the code of my test app:
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
int i = 0;
try {
while (i < 10000) {
RunnableDemo temp = new RunnableDemo("Thread-"
+ String.valueOf(i));
temp.start();
i++;
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class RunnableDemo implements Runnable {
private Thread t;
private String threadName;
InetAddress host = null;
int port = 9090;
RunnableDemo(String name) {
threadName = name;
System.err.println("Creating " + threadName);
}
public void run() {
System.err.println("Running " + threadName);
try {
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress(host, port));
while (!socketChannel.finishConnect())
;
System.out.println("Thread " + threadName + " Connected");
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (true) {
if (socketChannel.read(buffer) > 0) {
buffer.flip();
byte[] bytes = new byte[buffer.limit()];
buffer.get(bytes);
System.out.println(threadName+ ":" + new String(bytes));
buffer.clear();
}
}
} catch (Exception e) {
System.out.println("Thread " + threadName + " interrupted.");
e.printStackTrace();
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start() {
System.out.println("Starting " + threadName);
try {
host = InetAddress.getByName("127.0.0.1");
if (t == null) {
t = new Thread(this, threadName);
t.start();
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
The test application runs but only 75 threads can connect to the server and all thread after 75th shows below exception:
java.net.ConnectException: Connection refused: connect
at sun.nio.ch.Net.connect0(Native Method)
at sun.nio.ch.Net.connect(Unknown Source)
at sun.nio.ch.Net.connect(Unknown Source)
at sun.nio.ch.SocketChannelImpl.connect(Unknown Source)
at net.behboodi.client.RunnableDemo.run(Main.java:48)
at java.lang.Thread.run(Unknown Source)
Is there any limits for number of concurrent connections to the socket? Or is there any limits on using port 127.0.0.1 and local host? The other idea is that maybe a java app or JVM can not create more than 75 thread.
I searched about them all, but do not find any answer that show me what of the above reasons is my main problem and how can I fixed the code so that I can test the app with more than 10000 concurrent thread?
Get rid of the sleep. The Selector already blocks. Sleeping in network code is just literally a waste of time. NB (1) You don't call finishConnect() in blocking mode, (2) you aren't connecting threads to a ServerChannel, you are connecting client sockets to a server socket, (3) your client code doesn't handle end of stream, and (4) this is not an echo server.
– EJP

How to do Java serialization with ObjectInputStream when using NIO Selector?

How can you read an object directly from a SocketChannel that is non-blocking? It's being accessed with a Selector. The following code is broken (it throws an IllegalBlockingModeException) and I don't know how to fix it, except for perhaps using ByteBuffer, which I'd rather not (for now, at least):
public static void main(String[] args) {
try {
Selector selector = Selector.open();
ServerSocketChannel listener = ServerSocketChannel.open();
listener.socket().bind(new InetSocketAddress(50001));
listener.configureBlocking(false);
listener.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select();
Iterator<SelectionKey> i = selector.selectedKeys().iterator();
while (i.hasNext()) {
SelectionKey key = i.next();
i.remove();
if (key.isReadable()) {
SocketChannel channel = (SocketChannel) key.channel();
ObjectInputStream ois = new ObjectInputStream(channel.socket().getInputStream());
String message = (String) ois.readObject();
System.out.println("Server received message: " + message);
}
}
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}

Java NIO client

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.*;
public class EchoServer {
private InetAddress addr;
private int port;
private Selector selector;
private Map<SocketChannel,List<byte[]>> dataMap;
public EchoServer(InetAddress addr, int port) throws IOException {
this.addr = addr;
this.port = port;
dataMap = new HashMap<SocketChannel,List<byte[]>>();
startServer();
}
private void startServer() throws IOException {
// create selector and channel
this.selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
// bind to port
InetSocketAddress listenAddr = new InetSocketAddress(this.addr, this.port);
serverChannel.socket().bind(listenAddr);
serverChannel.register(this.selector, SelectionKey.OP_ACCEPT);
log("Echo server ready. Ctrl-C to stop.");
// processing
while (true) {
// wait for events
this.selector.select();
// wakeup to work on selected keys
Iterator keys = this.selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = (SelectionKey) keys.next();
// this is necessary to prevent the same key from coming up
// again the next time around.
keys.remove();
if (! key.isValid()) {
continue;
}
if (key.isAcceptable()) {
this.accept(key);
}
else if (key.isReadable()) {
this.read(key);
}
else if (key.isWritable()) {
this.write(key);
}
else if (key.isConnectable()) {
this.doConnect(key);
}
}
}
}
private void doConnect(SelectionKey key) {
SocketChannel channel = (SocketChannel) key.channel();
if (channel.finishConnect()) {
/* success */
System.out.println("Connected");
} else {
/* failure */
System.out.println("failure");
}
}
public void connect(String hostname, int port) throws IOException {
SocketChannel clientChannel = SocketChannel.open();
clientChannel.configureBlocking(false);
clientChannel.connect(new InetSocketAddress(hostname,port));
clientChannel.register(selector,SelectionKey.OP_CONNECT);
clientChannel.write(ByteBuffer.wrap(("$Hello "+UserInfo[0]+"|").getBytes("US-ASCII")));
}
private void accept(SelectionKey key) throws IOException {
ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
SocketChannel channel = serverChannel.accept();
channel.configureBlocking(false);
// write welcome message
channel.write(ByteBuffer.wrap("Welcome, this is the echo server\r\n".getBytes("US-ASCII")));
Socket socket = channel.socket();
SocketAddress remoteAddr = socket.getRemoteSocketAddress();
log("Connected to: " + remoteAddr);
dataMap.put(channel, new ArrayList<byte[]>()); // register channel with selector for further IO
channel.register(this.selector, SelectionKey.OP_READ);
}
private void read(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(8192);
int numRead = -1;
try {
numRead = channel.read(buffer);
}
catch (IOException e) {
e.printStackTrace();
}
if (numRead == -1) {
this.dataMap.remove(channel);
Socket socket = channel.socket();
SocketAddress remoteAddr = socket.getRemoteSocketAddress();
log("Connection closed by client: " + remoteAddr);
channel.close();
key.cancel();
return;
}
byte[] data = new byte[numRead];
System.arraycopy(buffer.array(), 0, data, 0, numRead);
log("Got: " + new String(data, "US-ASCII"));
doEcho(key, data); // write back to client
}
private void write(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
List<byte[]> pendingData = this.dataMap.get(channel);
Iterator<byte[]> items = pendingData.iterator();
while (items.hasNext()) {
byte[] item = items.next();
items.remove();
channel.write(ByteBuffer.wrap(item));
}
key.interestOps(SelectionKey.OP_READ);
}
private void doEcho(SelectionKey key, byte[] data) {
SocketChannel channel = (SocketChannel) key.channel();
List<byte[]> pendingData = this.dataMap.get(channel);
pendingData.add(data);
key.interestOps(SelectionKey.OP_WRITE);
}
private static void log(String s) {
System.out.println(s);
}
public static void main(String[] args) throws Exception {
new EchoServer(null, 8989);
}
}
The program works with incoming connections. But when I make an outgoing connection, the program does not work. I need to make some connections in a row through the connect (String hostname, int port) and receive data in a method read(). The program stops working on the line clientChannel.register(...)
You need to check for a connectable key, e.g.
if (key.isConnectable()) {
this.doConnect(key);
}
...
private void doConnect(SelectionKey key) {
SocketChannel channel = (SocketChannel) key.channel();
if (channel.finishConnect()) {
/* success */
} else {
/* failure */
}
}
Use SocketChannel.finishConnect to determine whether the connection was established successfully.
This is my NIO Client example Ive been using. It gives a timed out open/write/read functions and is suitable for request-response messaging.
Tricky part is always how do parties recognize a packet is fully received. This example assumes
Server gets one_line_command+newline (client->server packet)
Client receives 1..n lines with ">>" terminator line without trailing newline in a terminator line (server->client packet)
you could specify terminator to be ">>\n" but readUntil needs small fix in a newline parser
You could write 4-byte length header, fixed size packet splitter or delimiter 0x27 byte but make sure it cannot be a value of data payload. NIO read() or write() never assumes you receive a full packet in one call. Or may read two or more packet bytes in one read() buffer. It is up to us make a packet parser not loosing bytes.
import java.util.*;
import java.io.*;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
public class DPSocket {
private boolean debug;
private String host;
private int port;
private String charset;
private ByteArrayOutputStream inBuffer;
private ByteBuffer buf;
private Selector selector;
private SocketChannel channel;
public DPSocket(String host, int port, String charset) {
this.charset = charset==null || charset.equals("") ? "UTF-8" : charset;
this.host = host;
this.port = port;
}
public boolean isDebug() { return debug; }
public void setDebug(boolean b) { debug=b; }
public void open(long timeout) throws IOException {
selector = Selector.open();
channel = SocketChannel.open();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_CONNECT);
channel.connect(new InetSocketAddress(host, port));
inBuffer = new ByteArrayOutputStream(1024);
buf = ByteBuffer.allocate(1*1024);
long sleep = Math.min(timeout, 1000);
while(timeout > 0) {
if (selector.select(sleep) < 1) {
timeout-=sleep;
continue;
}
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while(keys.hasNext()) {
SelectionKey key = keys.next();
keys.remove();
if (!key.isValid() || !key.isConnectable()) continue;
SocketChannel channel = (SocketChannel)key.channel();
if (channel.isConnectionPending()) {
channel.finishConnect();
channel.configureBlocking(false);
if (debug) System.out.println("finishConnect");
return; // we are ready to receive bytes
}
}
}
throw new IOException("Connection timed out");
}
public void close() {
try { if(channel!=null) channel.close(); } catch(Exception ex) { }
try { if(selector!=null) selector.close(); } catch(Exception ex) { }
inBuffer=null;
buf=null;
}
public void write(String data, long timeout) throws IOException {
write(data.getBytes(charset), timeout);
}
public void write(byte[] bytes, long timeout) throws IOException {
ByteBuffer outBuffer = ByteBuffer.wrap(bytes);
channel.register(selector, SelectionKey.OP_WRITE);
long sleep = Math.min(timeout, 1000);
while(timeout > 0) {
if (selector.select(sleep) < 1) {
timeout-=sleep;
continue;
}
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while(keys.hasNext()) {
SelectionKey key = keys.next();
keys.remove();
if (!key.isValid() || !key.isWritable()) continue;
SocketChannel channel = (SocketChannel)key.channel();
if (debug) System.out.println("write remaining="+outBuffer.remaining());
channel.write(outBuffer);
if (debug) System.out.println("write remaining="+outBuffer.remaining());
if (outBuffer.remaining()<1)
return;
}
}
throw new IOException("Write timed out");
}
public List<String> readUntil(String terminator, long timeout, boolean trimLines) throws IOException {
return readUntil(new String[]{terminator}, timeout, trimLines);
}
public List<String> readUntil(String[] terminators, long timeout, boolean trimLines) throws IOException {
List<String> lines = new ArrayList<String>(12);
inBuffer.reset();
// End of packet terminator strings, line startsWith "aabbcc" string.
byte[][] arrTerminators = new byte[terminators.length][];
int[] idxTerminators = new int[terminators.length];
for(int idx=0; idx < terminators.length; idx++) {
arrTerminators[idx] = terminators[idx].getBytes(charset);
idxTerminators[idx] = 0;
}
int idxLineByte=-1;
channel.register(selector, SelectionKey.OP_READ);
long sleep = Math.min(timeout, 1000);
while(timeout>0) {
if (selector.select(sleep) < 1) {
timeout-=sleep;
continue;
}
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while(keys.hasNext()) {
SelectionKey key = keys.next();
keys.remove();
if (!key.isValid() || !key.isReadable()) continue;
SocketChannel channel = (SocketChannel)key.channel();
buf.clear();
int len = channel.read(buf);
if (len == -1) throw new IOException("Socket disconnected");
buf.flip();
for(int idx=0; idx<len; idx++) {
byte cb = buf.get(idx);
if (cb!='\n') {
idxLineByte++;
inBuffer.write(cb);
for(int idxter=0; idxter < arrTerminators.length; idxter++) {
byte[] arrTerminator = arrTerminators[idxter];
if (idxLineByte==idxTerminators[idxter]
&& arrTerminator[ idxTerminators[idxter] ]==cb) {
idxTerminators[idxter]++;
if (idxTerminators[idxter]==arrTerminator.length)
return lines;
} else idxTerminators[idxter]=0;
}
} else {
String line = inBuffer.toString(charset);
lines.add(trimLines ? line.trim() : line);
inBuffer.reset();
idxLineByte=-1;
for(int idxter=0; idxter<arrTerminators.length; idxter++)
idxTerminators[idxter]=0;
}
}
}
}
throw new IOException("Read timed out");
}
// **************************
// *** test socket client ***
// **************************
public static void main(String[] args) throws Exception {
String NEWLINE = "\n";
int TIMEOUT=5000;
DPSocket dps = new DPSocket("myserver.com", 1234, "UTF-8");
dps.setDebug(true);
try {
List<String> lines;
dps.open(15000);
dps.write("Command1 arg1 arg2"+NEWLINE, TIMEOUT);
lines = dps.readUntil(">>", TIMEOUT, true);
dps.write("Command2 arg1 arg2"+NEWLINE, TIMEOUT);
lines = dps.readUntil(">>", TIMEOUT, true);
} catch (Exception ex) {
String msg = ex.getMessage();
if (msg==null) msg = ex.getClass().getName();
if (msg.contains("timed out") || msg.contains("Invalid command ")) {
System.out.println("ERROR: " + ex.getMessage());
} else {
System.out.print("ERROR: ");
ex.printStackTrace();
}
} finally {
dps.close();
}
}
}

Categories