/*
* Copyright 2008-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.nominanuda.zen.obj;
import static com.nominanuda.zen.common.Str.UTF8;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Test;
public class ByteBufferTransitTest {
int dbPort = 19999;
int webPort = 19998;
int webCliReadBufSize = 65535;
int nbytes = 4 * 65535;
@Test
public void test() throws Exception {
Server dbSrv = new Server(dbPort, new DbHandler());
Server webSrv = new Server(webPort, new WebHandler());
ExecutorService tp = Executors.newCachedThreadPool();
tp.execute(dbSrv);
tp.execute(webSrv);
Thread.sleep(2000);
WebClient webCli = new WebClient();
webCli.run();
}
class DbHandler implements ChannelHandler {
public void handle(SocketChannel socketChannel) {
try {
int bufsize = 4096;
ByteBuffer wbuf = ByteBuffer.allocate(bufsize);
int nints = nbytes / 4;
int nintsPerBuf = bufsize / 4;
int nintsWrittenToBuf = 0;
for(int i = 0; i < nints; i++) {
wbuf.putInt(i);
nintsWrittenToBuf++;
if(nintsWrittenToBuf >= nintsPerBuf) {
wbuf.flip();
while(wbuf.hasRemaining()) {
socketChannel.write(wbuf);
}
wbuf.clear();
}
}
//socketChannel.close();
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
class WebHandler implements ChannelHandler {
public void handle(SocketChannel webChannel) {
try {
SocketChannel dbChannel = SocketChannel.open();
dbChannel.connect(new InetSocketAddress("localhost", dbPort));
int readBufSize = 4096;
ByteBuffer rbuf = ByteBuffer.allocate(readBufSize);
List<ByteBuffer> l = new LinkedList<ByteBuffer>();
int tot = 0;
int nread = 0;
while((nread = dbChannel.read(rbuf)) >= 0) {
if(rbuf.remaining() < 1) {
l.add(rbuf);
rbuf = ByteBuffer.allocate(readBufSize);
}
tot += nread;
if(nbytes == tot) {
break;
}
}
l.add(rbuf);
for(ByteBuffer b : l) {
b.flip();
while(b.hasRemaining()) {
webChannel.write(b);
}
}
//webChannel.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
class WebClient implements Runnable {
public void run() {
try {
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("localhost", webPort));
String req = "GET /foo HTTP/1.1\r\n\r\n";
ByteBuffer wbuf = ByteBuffer.allocate(req.getBytes(UTF8).length);
wbuf.clear();
wbuf.put(req.getBytes());
wbuf.flip();
while(wbuf.hasRemaining()) {
socketChannel.write(wbuf);
}
System.err.println("WebClient sent request:"+req);
ByteBuffer rbuf = ByteBuffer.allocate(webCliReadBufSize);
int tot = 0;
int nread = 0;
while((nread = socketChannel.read(rbuf)) >= 0) {
System.err.println("WebClient received:"+nread);
rbuf.clear();
tot += nread;
if(nbytes == tot) {
break;
}
}
System.err.println("WebClient received total:"+tot);
} catch(Exception e) {
e.printStackTrace();
}
}
}
static class Server implements Runnable {
final int port;
final ChannelHandler handler;
public Server(final int port, final ChannelHandler handler) {
this.handler = handler;
this.port = port;
}
public void run() {
try {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
ServerSocket ss = serverSocketChannel.socket();
ss.setReuseAddress(true);
ss.bind(new InetSocketAddress(port));
while (true) {
SocketChannel socketChannel = serverSocketChannel.accept();
if(socketChannel != null) {
handler.handle(socketChannel);
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
interface ChannelHandler {
void handle(SocketChannel socketChannel);
}
}