Clean up the examples
Motivation: The examples have not been updated since long time ago, showing various issues fixed in this commit. Modifications: - Overall simplification to reduce LoC - Use system properties to get options instead of parsing args. - Minimize option validation - Just use System.out/err instead of Logger - Do not pass config as parameters - just access it directly - Move the main logic to main(String[]) instead of creating a new instance meaninglessly - Update netty-build-21 to make checkstyle not complain - Remove 'throws Exception' clause if possible - Line wrap at 120 (previously at 80) - Add an option to enable SSL for most examples - Use ChannelFuture.sync() instead of await() - Use System.out for the actual result. Use System.err otherwise. - Delete examples that are not very useful: - websocket/html5 - websocketx/sslserver - localecho/multithreaded - Add run-example.sh which simplifies launching an example from command line Result: Shorter and simpler examples. A user can focus more on what it actually does than miscellaneous stuff. A user can launch an example very easily.
This commit is contained in:
parent
aa2c6b77e3
commit
ba28679775
16
pom.xml
16
pom.xml
@ -726,10 +726,24 @@
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>netty-build</artifactId>
|
||||
<version>20</version>
|
||||
<version>21</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.3</version>
|
||||
<configuration>
|
||||
<executable>${java.home}/bin/java</executable>
|
||||
<commandlineArgs>
|
||||
-classpath %classpath
|
||||
${argLine.example}
|
||||
${exampleClass}
|
||||
</commandlineArgs>
|
||||
<classpathScope>runtime</classpathScope>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
87
run-example.sh
Executable file
87
run-example.sh
Executable file
@ -0,0 +1,87 @@
|
||||
#!/bin/bash -e
|
||||
EXAMPLE_MAP=(
|
||||
'discard-client:org.jboss.netty.example.discard.DiscardClient'
|
||||
'discard-server:org.jboss.netty.example.discard.DiscardServer'
|
||||
'echo-client:org.jboss.netty.example.echo.EchoClient'
|
||||
'echo-server:org.jboss.netty.example.echo.EchoServer'
|
||||
'factorial-client:org.jboss.netty.example.factorial.FactorialClient'
|
||||
'factorial-server:org.jboss.netty.example.factorial.FactorialServer'
|
||||
'http-snoop-client:org.jboss.netty.example.http.snoop.HttpSnoopClient'
|
||||
'http-snoop-server:org.jboss.netty.example.http.snoop.HttpSnoopServer'
|
||||
'http-file-server:org.jboss.netty.example.http.file.HttpStaticFileServer'
|
||||
'http-helloworld-server:org.jboss.netty.example.http.helloworld.HttpHelloWorldServer'
|
||||
'http-upload-client:org.jboss.netty.example.http.upload.HttpUploadClient'
|
||||
'http-upload-server:org.jboss.netty.example.http.upload.HttpUploadServer'
|
||||
'websocket-client:org.jboss.netty.example.websocketx.client.WebSocketClient'
|
||||
'websocket-server:org.jboss.netty.example.websocketx.server.WebSocketServer'
|
||||
'localtime-client:org.jboss.netty.example.localtime.LocalTimeClient'
|
||||
'localtime-server:org.jboss.netty.example.localtime.LocalTimeServer'
|
||||
'objectecho-client:org.jboss.netty.example.objectecho.ObjectEchoClient'
|
||||
'objectecho-server:org.jboss.netty.example.objectecho.ObjectEchoServer'
|
||||
'quote-client:org.jboss.netty.example.qotm.QuoteOfTheMomentClient'
|
||||
'quote-server:org.jboss.netty.example.qotm.QuoteOfTheMomentServer'
|
||||
'securechat-client:org.jboss.netty.example.securechat.SecureChatClient'
|
||||
'securechat-server:org.jboss.netty.example.securechat.SecureChatServer'
|
||||
'telnet-client:org.jboss.netty.example.telnet.TelnetClient'
|
||||
'telnet-server:org.jboss.netty.example.telnet.TelnetServer'
|
||||
'proxy-server:org.jboss.netty.example.proxy.HexDumpProxy'
|
||||
'uptime-client:org.jboss.netty.example.uptime.UptimeClient'
|
||||
'local-transport:org.jboss.netty.example.local.LocalExample'
|
||||
)
|
||||
|
||||
EXAMPLE=''
|
||||
EXAMPLE_CLASS=''
|
||||
EXAMPLE_ARGS='-D_'
|
||||
I=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
ARG="$1"
|
||||
shift
|
||||
if [[ "$ARG" =~ (^-.+) ]]; then
|
||||
EXAMPLE_ARGS="$EXAMPLE_ARGS $ARG"
|
||||
else
|
||||
EXAMPLE="$ARG"
|
||||
for E in "${EXAMPLE_MAP[@]}"; do
|
||||
KEY="${E%%:*}"
|
||||
VAL="${E##*:}"
|
||||
if [[ "$EXAMPLE" == "$KEY" ]]; then
|
||||
EXAMPLE_CLASS="$VAL"
|
||||
break
|
||||
fi
|
||||
done
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z "$EXAMPLE" ]] || [[ -z "$EXAMPLE_CLASS" ]] || [[ $# -ne 0 ]]; then
|
||||
echo " Usage: $0 [-D<name>[=<value>] ...] <example-name>" >&2
|
||||
echo "Example: $0 -Dport=8443 -Dssl http-server" >&2
|
||||
echo " $0 -Dhost=127.0.0.1 -Dport=8009 echo-client" >&2
|
||||
echo >&2
|
||||
echo "Available examples:" >&2
|
||||
echo >&2
|
||||
I=0
|
||||
for E in "${EXAMPLE_MAP[@]}"; do
|
||||
if [[ $I -eq 0 ]]; then
|
||||
echo -n ' '
|
||||
fi
|
||||
|
||||
printf '%-24s' "${E%%:*}"
|
||||
((I++)) || true
|
||||
|
||||
if [[ $I -eq 2 ]]; then
|
||||
I=0
|
||||
echo
|
||||
fi
|
||||
done >&2
|
||||
if [[ $I -ne 0 ]]; then
|
||||
echo >&2
|
||||
fi
|
||||
echo >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "`dirname "$0"`"
|
||||
echo "[INFO] Running: $EXAMPLE ($EXAMPLE_CLASS $EXAMPLE_ARGS)"
|
||||
exec mvn -nsu compile exec:exec -DargLine.example="$EXAMPLE_ARGS" -DexampleClass="$EXAMPLE_CLASS"
|
||||
|
@ -15,75 +15,63 @@
|
||||
*/
|
||||
package org.jboss.netty.example.discard;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.Channels;
|
||||
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Keeps sending random data to the specified address.
|
||||
*/
|
||||
public class DiscardClient {
|
||||
public final class DiscardClient {
|
||||
|
||||
private final String host;
|
||||
private final int port;
|
||||
private final int firstMessageSize;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final String HOST = System.getProperty("host", "127.0.0.1");
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8009"));
|
||||
static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
|
||||
|
||||
public DiscardClient(String host, int port, int firstMessageSize) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.firstMessageSize = firstMessageSize;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the client.
|
||||
// Configure the bootstrap.
|
||||
ClientBootstrap bootstrap = new ClientBootstrap(
|
||||
new NioClientSocketChannelFactory(
|
||||
Executors.newCachedThreadPool(),
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
// Set up the pipeline factory.
|
||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
return Channels.pipeline(
|
||||
new DiscardClientHandler(firstMessageSize));
|
||||
}
|
||||
});
|
||||
try {
|
||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline p = Channels.pipeline();
|
||||
if (sslCtx != null) {
|
||||
p.addLast("ssl", sslCtx.newHandler(HOST, PORT));
|
||||
}
|
||||
p.addLast("discard", new DiscardClientHandler());
|
||||
return p;
|
||||
}
|
||||
});
|
||||
|
||||
// Start the connection attempt.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
|
||||
// Start the connection attempt.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(HOST, PORT));
|
||||
|
||||
// Wait until the connection is closed or the connection attempt fails.
|
||||
future.getChannel().getCloseFuture().awaitUninterruptibly();
|
||||
|
||||
// Shut down thread pools to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Print usage if no argument is specified.
|
||||
if (args.length < 2 || args.length > 3) {
|
||||
System.err.println(
|
||||
"Usage: " + DiscardClient.class.getSimpleName() +
|
||||
" <host> <port> [<first message size>]");
|
||||
return;
|
||||
// Wait until the connection is closed or the connection attempt fails.
|
||||
future.getChannel().getCloseFuture().sync();
|
||||
} finally {
|
||||
// Shut down thread pools to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
}
|
||||
|
||||
// Parse options.
|
||||
final String host = args[0];
|
||||
final int port = Integer.parseInt(args[1]);
|
||||
final int firstMessageSize;
|
||||
if (args.length == 3) {
|
||||
firstMessageSize = Integer.parseInt(args[2]);
|
||||
} else {
|
||||
firstMessageSize = 256;
|
||||
}
|
||||
|
||||
new DiscardClient(host, port, firstMessageSize).run();
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.discard;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
@ -35,18 +32,11 @@ import org.jboss.netty.channel.WriteCompletionEvent;
|
||||
*/
|
||||
public class DiscardClientHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
DiscardClientHandler.class.getName());
|
||||
|
||||
private long transferredBytes;
|
||||
private final byte[] content;
|
||||
|
||||
public DiscardClientHandler(int messageSize) {
|
||||
if (messageSize <= 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"messageSize: " + messageSize);
|
||||
}
|
||||
content = new byte[messageSize];
|
||||
public DiscardClientHandler() {
|
||||
content = new byte[DiscardClient.SIZE];
|
||||
}
|
||||
|
||||
public long getTransferredBytes() {
|
||||
@ -57,7 +47,7 @@ public class DiscardClientHandler extends SimpleChannelUpstreamHandler {
|
||||
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
if (((ChannelStateEvent) e).getState() != ChannelState.INTEREST_OPS) {
|
||||
logger.info(e.toString());
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,10 +80,7 @@ public class DiscardClientHandler extends SimpleChannelUpstreamHandler {
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
// Close the connection when an exception is raised.
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
||||
|
@ -15,51 +15,53 @@
|
||||
*/
|
||||
package org.jboss.netty.example.discard;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.Channels;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Discards any incoming data.
|
||||
*/
|
||||
public class DiscardServer {
|
||||
public final class DiscardServer {
|
||||
|
||||
private final int port;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8009"));
|
||||
|
||||
public DiscardServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
// Configure the bootstrap.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
||||
new NioServerSocketChannelFactory(
|
||||
Executors.newCachedThreadPool(),
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
// Set up the pipeline factory.
|
||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
return Channels.pipeline(new DiscardServerHandler());
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline p = Channels.pipeline();
|
||||
if (sslCtx != null) {
|
||||
p.addLast("ssl", sslCtx.newHandler());
|
||||
}
|
||||
p.addLast("discard", new DiscardServerHandler());
|
||||
return p;
|
||||
}
|
||||
});
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
new DiscardServer(port).run();
|
||||
bootstrap.bind(new InetSocketAddress(PORT));
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.discard;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.ChannelEvent;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
@ -31,9 +28,6 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
*/
|
||||
public class DiscardServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
DiscardServerHandler.class.getName());
|
||||
|
||||
private long transferredBytes;
|
||||
|
||||
public long getTransferredBytes() {
|
||||
@ -43,7 +37,7 @@ public class DiscardServerHandler extends SimpleChannelUpstreamHandler {
|
||||
@Override
|
||||
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
logger.info(e.toString());
|
||||
System.err.println(e);
|
||||
}
|
||||
|
||||
// Let SimpleChannelHandler call actual event handler methods below.
|
||||
@ -59,10 +53,7 @@ public class DiscardServerHandler extends SimpleChannelUpstreamHandler {
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
// Close the connection when an exception is raised.
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
}
|
||||
|
@ -15,15 +15,17 @@
|
||||
*/
|
||||
package org.jboss.netty.example.echo;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.Channels;
|
||||
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Sends one message when a connection is open and echoes back any received
|
||||
@ -31,62 +33,51 @@ import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
||||
* traffic between the echo client and server by sending the first message to
|
||||
* the server.
|
||||
*/
|
||||
public class EchoClient {
|
||||
public final class EchoClient {
|
||||
|
||||
private final String host;
|
||||
private final int port;
|
||||
private final int firstMessageSize;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final String HOST = System.getProperty("host", "127.0.0.1");
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
|
||||
static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
|
||||
|
||||
public EchoClient(String host, int port, int firstMessageSize) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.firstMessageSize = firstMessageSize;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.git
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the client.
|
||||
// Configure the bootstrap.
|
||||
ClientBootstrap bootstrap = new ClientBootstrap(
|
||||
new NioClientSocketChannelFactory(
|
||||
Executors.newCachedThreadPool(),
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
// Set up the pipeline factory.
|
||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
return Channels.pipeline(
|
||||
new EchoClientHandler(firstMessageSize));
|
||||
}
|
||||
});
|
||||
try {
|
||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline p = Channels.pipeline();
|
||||
if (sslCtx != null) {
|
||||
p.addLast("ssl", sslCtx.newHandler(HOST, PORT));
|
||||
}
|
||||
p.addLast("echo", new EchoClientHandler());
|
||||
return p;
|
||||
}
|
||||
});
|
||||
bootstrap.setOption("tcpNoDelay", true);
|
||||
bootstrap.setOption("receiveBufferSize", 1048576);
|
||||
bootstrap.setOption("sendBufferSize", 1048576);
|
||||
|
||||
// Start the connection attempt.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
|
||||
// Start the connection attempt.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(HOST, PORT));
|
||||
|
||||
// Wait until the connection is closed or the connection attempt fails.
|
||||
future.getChannel().getCloseFuture().awaitUninterruptibly();
|
||||
|
||||
// Shut down thread pools to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Print usage if no argument is specified.
|
||||
if (args.length < 2 || args.length > 3) {
|
||||
System.err.println(
|
||||
"Usage: " + EchoClient.class.getSimpleName() +
|
||||
" <host> <port> [<first message size>]");
|
||||
return;
|
||||
// Wait until the connection is closed or the connection attempt fails.
|
||||
future.getChannel().getCloseFuture().sync();
|
||||
} finally {
|
||||
// Shut down thread pools to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
}
|
||||
|
||||
// Parse options.
|
||||
final String host = args[0];
|
||||
final int port = Integer.parseInt(args[1]);
|
||||
final int firstMessageSize;
|
||||
if (args.length == 3) {
|
||||
firstMessageSize = Integer.parseInt(args[2]);
|
||||
} else {
|
||||
firstMessageSize = 256;
|
||||
}
|
||||
|
||||
new EchoClient(host, port, firstMessageSize).run();
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.echo;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
@ -27,6 +23,8 @@ import org.jboss.netty.channel.ExceptionEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* Handler implementation for the echo client. It initiates the ping-pong
|
||||
* traffic between the echo client and server by sending the first message to
|
||||
@ -34,21 +32,14 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
*/
|
||||
public class EchoClientHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
EchoClientHandler.class.getName());
|
||||
|
||||
private final ChannelBuffer firstMessage;
|
||||
private final AtomicLong transferredBytes = new AtomicLong();
|
||||
|
||||
/**
|
||||
* Creates a client-side handler.
|
||||
*/
|
||||
public EchoClientHandler(int firstMessageSize) {
|
||||
if (firstMessageSize <= 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"firstMessageSize: " + firstMessageSize);
|
||||
}
|
||||
firstMessage = ChannelBuffers.buffer(firstMessageSize);
|
||||
public EchoClientHandler() {
|
||||
firstMessage = ChannelBuffers.buffer(EchoClient.SIZE);
|
||||
for (int i = 0; i < firstMessage.capacity(); i ++) {
|
||||
firstMessage.writeByte((byte) i);
|
||||
}
|
||||
@ -59,29 +50,23 @@ public class EchoClientHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelConnected(
|
||||
ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
// Send the first message. Server will not send anything here
|
||||
// because the firstMessage's capacity is 0.
|
||||
e.getChannel().write(firstMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(
|
||||
ChannelHandlerContext ctx, MessageEvent e) {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
// Send back the received message to the remote peer.
|
||||
transferredBytes.addAndGet(((ChannelBuffer) e.getMessage()).readableBytes());
|
||||
e.getChannel().write(e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
// Close the connection when an exception is raised.
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
}
|
||||
|
@ -15,51 +15,57 @@
|
||||
*/
|
||||
package org.jboss.netty.example.echo;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.Channels;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Echoes back any received data from a client.
|
||||
*/
|
||||
public class EchoServer {
|
||||
public final class EchoServer {
|
||||
|
||||
private final int port;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
|
||||
|
||||
public EchoServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
// Configure the bootstrap.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
||||
new NioServerSocketChannelFactory(
|
||||
Executors.newCachedThreadPool(),
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
// Set up the pipeline factory.
|
||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
return Channels.pipeline(new EchoServerHandler());
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline p = Channels.pipeline();
|
||||
if (sslCtx != null) {
|
||||
p.addLast("ssl", sslCtx.newHandler());
|
||||
}
|
||||
p.addLast("echo", new EchoServerHandler());
|
||||
return p;
|
||||
}
|
||||
});
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
}
|
||||
bootstrap.setOption("child.tcpNoDelay", true);
|
||||
bootstrap.setOption("child.receiveBufferSize", 1048576);
|
||||
bootstrap.setOption("child.sendBufferSize", 1048576);
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
new EchoServer(port).run();
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(PORT));
|
||||
}
|
||||
}
|
||||
|
@ -15,24 +15,19 @@
|
||||
*/
|
||||
package org.jboss.netty.example.echo;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ExceptionEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* Handler implementation for the echo server.
|
||||
*/
|
||||
public class EchoServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
EchoServerHandler.class.getName());
|
||||
|
||||
private final AtomicLong transferredBytes = new AtomicLong();
|
||||
|
||||
public long getTransferredBytes() {
|
||||
@ -40,21 +35,16 @@ public class EchoServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(
|
||||
ChannelHandlerContext ctx, MessageEvent e) {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
// Send back the received message to the remote peer.
|
||||
transferredBytes.addAndGet(((ChannelBuffer) e.getMessage()).readableBytes());
|
||||
e.getChannel().write(e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
// Close the connection when an exception is raised.
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
}
|
||||
|
@ -15,14 +15,14 @@
|
||||
*/
|
||||
package org.jboss.netty.example.factorial;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.frame.CorruptedFrameException;
|
||||
import org.jboss.netty.handler.codec.frame.FrameDecoder;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Decodes the binary representation of a {@link BigInteger} prepended
|
||||
* with a magic number ('F' or 0x46) and a 32-bit integer length prefix into a
|
||||
@ -32,8 +32,7 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder;
|
||||
public class BigIntegerDecoder extends FrameDecoder {
|
||||
|
||||
@Override
|
||||
protected Object decode(
|
||||
ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
|
||||
// Wait until the length prefix is available.
|
||||
if (buffer.readableBytes() < 5) {
|
||||
return null;
|
||||
@ -45,8 +44,7 @@ public class BigIntegerDecoder extends FrameDecoder {
|
||||
int magicNumber = buffer.readUnsignedByte();
|
||||
if (magicNumber != 'F') {
|
||||
buffer.resetReaderIndex();
|
||||
throw new CorruptedFrameException(
|
||||
"Invalid magic number: " + magicNumber);
|
||||
throw new CorruptedFrameException("Invalid magic number: " + magicNumber);
|
||||
}
|
||||
|
||||
// Wait until the whole data is available.
|
||||
|
@ -15,76 +15,59 @@
|
||||
*/
|
||||
package org.jboss.netty.example.factorial;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Sends a sequence of integers to a {@link FactorialServer} to calculate
|
||||
* the factorial of the specified integer.
|
||||
*/
|
||||
public class FactorialClient {
|
||||
public final class FactorialClient {
|
||||
|
||||
private final String host;
|
||||
private final int port;
|
||||
private final int count;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final String HOST = System.getProperty("host", "127.0.0.1");
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8322"));
|
||||
static final int COUNT = Integer.parseInt(System.getProperty("count", "1000"));
|
||||
|
||||
public FactorialClient(String host, int port, int count) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.count = count;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the client.
|
||||
// Configure the bootstrap.
|
||||
ClientBootstrap bootstrap = new ClientBootstrap(
|
||||
new NioClientSocketChannelFactory(
|
||||
Executors.newCachedThreadPool(),
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
// Set up the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new FactorialClientPipelineFactory(count));
|
||||
try {
|
||||
bootstrap.setPipelineFactory(new FactorialClientPipelineFactory(sslCtx));
|
||||
|
||||
// Make a new connection.
|
||||
ChannelFuture connectFuture =
|
||||
bootstrap.connect(new InetSocketAddress(host, port));
|
||||
// Make a new connection.
|
||||
ChannelFuture connectFuture = bootstrap.connect(new InetSocketAddress(HOST, PORT));
|
||||
|
||||
// Wait until the connection is made successfully.
|
||||
Channel channel = connectFuture.awaitUninterruptibly().getChannel();
|
||||
// Wait until the connection is made successfully.
|
||||
Channel channel = connectFuture.sync().getChannel();
|
||||
|
||||
// Get the handler instance to retrieve the answer.
|
||||
FactorialClientHandler handler =
|
||||
(FactorialClientHandler) channel.getPipeline().getLast();
|
||||
// Get the handler instance to retrieve the answer.
|
||||
FactorialClientHandler handler = (FactorialClientHandler) channel.getPipeline().getLast();
|
||||
|
||||
// Print out the answer.
|
||||
System.err.format(
|
||||
"Factorial of %,d is: %,d", count, handler.getFactorial());
|
||||
|
||||
// Shut down all thread pools to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Print usage if no argument is specified.
|
||||
if (args.length != 3) {
|
||||
System.err.println(
|
||||
"Usage: " + FactorialClient.class.getSimpleName() +
|
||||
" <host> <port> <count>");
|
||||
return;
|
||||
// Print out the answer.
|
||||
System.err.format("Factorial of %,d is: %,d", COUNT, handler.getFactorial());
|
||||
} finally {
|
||||
// Shut down all thread pools to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
}
|
||||
|
||||
// Parse options.
|
||||
String host = args[0];
|
||||
int port = Integer.parseInt(args[1]);
|
||||
int count = Integer.parseInt(args[2]);
|
||||
if (count <= 0) {
|
||||
throw new IllegalArgumentException("count must be a positive integer.");
|
||||
}
|
||||
|
||||
new FactorialClient(host, port, count).run();
|
||||
}
|
||||
}
|
||||
|
@ -15,12 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.factorial;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelEvent;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
@ -31,6 +25,10 @@ import org.jboss.netty.channel.ExceptionEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
/**
|
||||
* Handler for a client-side channel. This handler maintains stateful
|
||||
* information which is specific to a certain channel using member variables.
|
||||
@ -40,39 +38,32 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
*/
|
||||
public class FactorialClientHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
FactorialClientHandler.class.getName());
|
||||
|
||||
// Stateful properties
|
||||
private int i = 1;
|
||||
private int receivedMessages;
|
||||
private final int count;
|
||||
final BlockingQueue<BigInteger> answer = new LinkedBlockingQueue<BigInteger>();
|
||||
|
||||
public FactorialClientHandler(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public BigInteger getFactorial() {
|
||||
boolean interrupted = false;
|
||||
for (;;) {
|
||||
try {
|
||||
BigInteger factorial = answer.take();
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
try {
|
||||
for (;;) {
|
||||
try {
|
||||
return answer.take();
|
||||
} catch (InterruptedException ignore) {
|
||||
interrupted = true;
|
||||
}
|
||||
return factorial;
|
||||
} catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
}
|
||||
} finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUpstream(
|
||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
logger.info(e.toString());
|
||||
System.err.println(e);
|
||||
}
|
||||
super.handleUpstream(ctx, e);
|
||||
}
|
||||
@ -91,7 +82,7 @@ public class FactorialClientHandler extends SimpleChannelUpstreamHandler {
|
||||
public void messageReceived(
|
||||
ChannelHandlerContext ctx, final MessageEvent e) {
|
||||
receivedMessages ++;
|
||||
if (receivedMessages == count) {
|
||||
if (receivedMessages == FactorialClient.COUNT) {
|
||||
// Offer the answer after closing the connection.
|
||||
e.getChannel().close().addListener(new ChannelFutureListener() {
|
||||
public void operationComplete(ChannelFuture future) {
|
||||
@ -103,19 +94,15 @@ public class FactorialClientHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
||||
private void sendNumbers(ChannelStateEvent e) {
|
||||
Channel channel = e.getChannel();
|
||||
while (channel.isWritable()) {
|
||||
if (i <= count) {
|
||||
if (i <= FactorialClient.COUNT) {
|
||||
channel.write(i);
|
||||
i ++;
|
||||
} else {
|
||||
|
@ -15,29 +15,34 @@
|
||||
*/
|
||||
package org.jboss.netty.example.factorial;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.handler.codec.compression.ZlibDecoder;
|
||||
import org.jboss.netty.handler.codec.compression.ZlibEncoder;
|
||||
import org.jboss.netty.handler.codec.compression.ZlibWrapper;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
/**
|
||||
* Creates a newly configured {@link ChannelPipeline} for a client-side channel.
|
||||
*/
|
||||
public class FactorialClientPipelineFactory implements
|
||||
ChannelPipelineFactory {
|
||||
public class FactorialClientPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
private final int count;
|
||||
private final SslContext sslCtx;
|
||||
|
||||
public FactorialClientPipelineFactory(int count) {
|
||||
this.count = count;
|
||||
public FactorialClientPipelineFactory(SslContext sslCtx) {
|
||||
this.sslCtx = sslCtx;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
// Enabls SSL if necessary.
|
||||
if (sslCtx != null) {
|
||||
pipeline.addLast("ssl", sslCtx.newHandler(FactorialClient.HOST, FactorialClient.PORT));
|
||||
}
|
||||
|
||||
// Enable stream compression (you can remove these two if unnecessary)
|
||||
pipeline.addLast("deflater", new ZlibEncoder(ZlibWrapper.GZIP));
|
||||
pipeline.addLast("inflater", new ZlibDecoder(ZlibWrapper.GZIP));
|
||||
@ -47,7 +52,7 @@ public class FactorialClientPipelineFactory implements
|
||||
pipeline.addLast("encoder", new NumberEncoder());
|
||||
|
||||
// and then business logic.
|
||||
pipeline.addLast("handler", new FactorialClientHandler(count));
|
||||
pipeline.addLast("handler", new FactorialClientHandler());
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
@ -15,25 +15,33 @@
|
||||
*/
|
||||
package org.jboss.netty.example.factorial;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Receives a sequence of integers from a {@link FactorialClient} to calculate
|
||||
* the factorial of the specified integer.
|
||||
*/
|
||||
public class FactorialServer {
|
||||
public final class FactorialServer {
|
||||
|
||||
private final int port;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8322"));
|
||||
|
||||
public FactorialServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
||||
new NioServerSocketChannelFactory(
|
||||
@ -41,19 +49,9 @@ public class FactorialServer {
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
// Set up the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new FactorialServerPipelineFactory());
|
||||
bootstrap.setPipelineFactory(new FactorialServerPipelineFactory(sslCtx));
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
new FactorialServer(port).run();
|
||||
bootstrap.bind(new InetSocketAddress(PORT));
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.factorial;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Formatter;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jboss.netty.channel.ChannelEvent;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ChannelStateEvent;
|
||||
@ -27,6 +22,9 @@ import org.jboss.netty.channel.ExceptionEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Formatter;
|
||||
|
||||
/**
|
||||
* Handler for a server-side channel. This handler maintains stateful
|
||||
* information which is specific to a certain channel using member variables.
|
||||
@ -36,26 +34,20 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
*/
|
||||
public class FactorialServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
FactorialServerHandler.class.getName());
|
||||
|
||||
// Stateful properties.
|
||||
private int lastMultiplier = 1;
|
||||
private BigInteger factorial = new BigInteger(new byte[] { 1 });
|
||||
|
||||
@Override
|
||||
public void handleUpstream(
|
||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
logger.info(e.toString());
|
||||
System.err.println(e);
|
||||
}
|
||||
super.handleUpstream(ctx, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(
|
||||
ChannelHandlerContext ctx, MessageEvent e) {
|
||||
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
// Calculate the cumulative factorial and send it to the client.
|
||||
BigInteger number;
|
||||
if (e.getMessage() instanceof BigInteger) {
|
||||
@ -69,19 +61,13 @@ public class FactorialServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelDisconnected(ChannelHandlerContext ctx,
|
||||
ChannelStateEvent e) throws Exception {
|
||||
logger.info(new Formatter().format(
|
||||
"Factorial of %,d is: %,d", lastMultiplier, factorial).toString());
|
||||
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
System.err.println(new Formatter().format("Factorial of %,d is: %,d", lastMultiplier, factorial));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
}
|
||||
|
@ -15,23 +15,33 @@
|
||||
*/
|
||||
package org.jboss.netty.example.factorial;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.handler.codec.compression.ZlibDecoder;
|
||||
import org.jboss.netty.handler.codec.compression.ZlibEncoder;
|
||||
import org.jboss.netty.handler.codec.compression.ZlibWrapper;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
/**
|
||||
* Creates a newly configured {@link ChannelPipeline} for a server-side channel.
|
||||
*/
|
||||
public class FactorialServerPipelineFactory implements
|
||||
ChannelPipelineFactory {
|
||||
public class FactorialServerPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
private final SslContext sslCtx;
|
||||
|
||||
public FactorialServerPipelineFactory(SslContext sslCtx) {
|
||||
this.sslCtx = sslCtx;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
if (sslCtx != null) {
|
||||
pipeline.addLast("ssl", sslCtx.newHandler());
|
||||
}
|
||||
|
||||
// Enable stream compression (you can remove these two if unnecessary)
|
||||
pipeline.addLast("deflater", new ZlibEncoder(ZlibWrapper.GZIP));
|
||||
pipeline.addLast("inflater", new ZlibDecoder(ZlibWrapper.GZIP));
|
||||
|
@ -15,14 +15,14 @@
|
||||
*/
|
||||
package org.jboss.netty.example.factorial;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Encodes a {@link Number} into the binary representation prepended with
|
||||
* a magic number ('F' or 0x46) and a 32-bit length prefix. For example, 42
|
||||
@ -31,8 +31,7 @@ import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
||||
public class NumberEncoder extends OneToOneEncoder {
|
||||
|
||||
@Override
|
||||
protected Object encode(
|
||||
ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
|
||||
protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) {
|
||||
if (!(msg instanceof Number)) {
|
||||
// Ignore what this encoder can't encode.
|
||||
return msg;
|
||||
|
@ -23,19 +23,21 @@ import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class HttpStaticFileServer {
|
||||
public final class HttpStaticFileServer {
|
||||
|
||||
private static final boolean useSsl = false; // Set to true to enable SSL.
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
|
||||
|
||||
private final SslContext sslCtx;
|
||||
private final int port;
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public HttpStaticFileServer(SslContext sslCtx, int port) {
|
||||
this.sslCtx = sslCtx;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
||||
new NioServerSocketChannelFactory(
|
||||
@ -46,25 +48,6 @@ public class HttpStaticFileServer {
|
||||
bootstrap.setPipelineFactory(new HttpStaticFileServerPipelineFactory(sslCtx));
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
|
||||
final SslContext sslCtx;
|
||||
if (useSsl) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
new HttpStaticFileServer(sslCtx, port).run();
|
||||
bootstrap.bind(new InetSocketAddress(PORT));
|
||||
}
|
||||
}
|
||||
|
@ -102,9 +102,9 @@ import static org.jboss.netty.handler.codec.http.HttpVersion.*;
|
||||
*/
|
||||
public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
public static final String HTTP_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
|
||||
public static final String HTTP_DATE_GMT_TIMEZONE = "GMT";
|
||||
public static final int HTTP_CACHE_SECONDS = 60;
|
||||
static final String HTTP_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
|
||||
static final String HTTP_DATE_GMT_TIMEZONE = "GMT";
|
||||
static final int HTTP_CACHE_SECONDS = 60;
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
@ -182,7 +182,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
public void operationProgressed(
|
||||
ChannelFuture future, long amount, long current, long total) {
|
||||
System.out.printf("%s: %d / %d (+%d)%n", path, current, total, amount);
|
||||
System.err.printf("%s: %d / %d (+%d)%n", path, current, total, amount);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -195,8 +195,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
||||
throws Exception {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
Channel ch = e.getChannel();
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof TooLongFrameException) {
|
||||
@ -240,9 +239,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
||||
private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
|
||||
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);
|
||||
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
|
||||
response.setContent(ChannelBuffers.copiedBuffer(
|
||||
"Failure: " + status.toString() + "\r\n",
|
||||
CharsetUtil.UTF_8));
|
||||
response.setContent(ChannelBuffers.copiedBuffer("Failure: " + status + "\r\n", CharsetUtil.UTF_8));
|
||||
|
||||
// Close the connection as soon as the error message is sent.
|
||||
ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
|
||||
@ -250,9 +247,6 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
/**
|
||||
* When file timestamp is the same as what the browser is sending up, send a "304 Not Modified"
|
||||
*
|
||||
* @param ctx
|
||||
* Context
|
||||
*/
|
||||
private static void sendNotModified(ChannelHandlerContext ctx) {
|
||||
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, NOT_MODIFIED);
|
||||
@ -264,9 +258,6 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
/**
|
||||
* Sets the Date header for the HTTP response
|
||||
*
|
||||
* @param response
|
||||
* HTTP response
|
||||
*/
|
||||
private static void setDateHeader(HttpResponse response) {
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
|
||||
@ -279,10 +270,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
||||
/**
|
||||
* Sets the Date and Cache headers for the HTTP Response
|
||||
*
|
||||
* @param response
|
||||
* HTTP response
|
||||
* @param fileToCache
|
||||
* file to extract content type
|
||||
* @param fileToCache the file to extract content type
|
||||
*/
|
||||
private static void setDateAndCacheHeaders(HttpResponse response, File fileToCache) {
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
|
||||
@ -296,21 +284,16 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
||||
time.add(Calendar.SECOND, HTTP_CACHE_SECONDS);
|
||||
response.headers().set(EXPIRES, dateFormatter.format(time.getTime()));
|
||||
response.headers().set(CACHE_CONTROL, "private, max-age=" + HTTP_CACHE_SECONDS);
|
||||
response.headers().set(
|
||||
LAST_MODIFIED, dateFormatter.format(new Date(fileToCache.lastModified())));
|
||||
response.headers().set(LAST_MODIFIED, dateFormatter.format(new Date(fileToCache.lastModified())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content type header for the HTTP Response
|
||||
*
|
||||
* @param response
|
||||
* HTTP response
|
||||
* @param file
|
||||
* file to extract content type
|
||||
* @param file the file to extract content type
|
||||
*/
|
||||
private static void setContentTypeHeader(HttpResponse response, File file) {
|
||||
MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
|
||||
response.headers().set(CONTENT_TYPE, mimeTypesMap.getContentType(file.getPath()));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public class HttpStaticFileServerPipelineFactory implements ChannelPipelineFacto
|
||||
this.sslCtx = sslCtx;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
public ChannelPipeline getPipeline() {
|
||||
// Create a default pipeline implementation.
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
|
@ -17,6 +17,8 @@ package org.jboss.netty.example.http.helloworld;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
@ -25,15 +27,21 @@ import java.util.concurrent.Executors;
|
||||
* An HTTP server that sends back the content of the received HTTP request
|
||||
* in a pretty plaintext form.
|
||||
*/
|
||||
public class HttpHelloWorldServer {
|
||||
public final class HttpHelloWorldServer {
|
||||
|
||||
private final int port;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
|
||||
|
||||
public HttpHelloWorldServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
||||
new NioServerSocketChannelFactory(
|
||||
@ -44,20 +52,9 @@ public class HttpHelloWorldServer {
|
||||
bootstrap.setOption("child.tcpNoDelay", true);
|
||||
|
||||
// Set up the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new HttpHelloWorldServerPipelineFactory());
|
||||
bootstrap.setPipelineFactory(new HttpHelloWorldServerPipelineFactory(sslCtx));
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
bootstrap.bind(new InetSocketAddress(PORT));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
new HttpHelloWorldServer(port).run();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public class HttpHelloWorldServerHandler extends SimpleChannelUpstreamHandler {
|
||||
private static final byte[] CONTENT = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
Object msg = e.getMessage();
|
||||
Channel ch = e.getChannel();
|
||||
if (msg instanceof HttpRequest) {
|
||||
@ -66,8 +66,7 @@ public class HttpHelloWorldServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
||||
throws Exception {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
@ -20,19 +20,25 @@ import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.handler.codec.http.HttpContentCompressor;
|
||||
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
|
||||
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
public class HttpHelloWorldServerPipelineFactory implements ChannelPipelineFactory {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
|
||||
private final SslContext sslCtx;
|
||||
|
||||
public HttpHelloWorldServerPipelineFactory(SslContext sslCtx) {
|
||||
this.sslCtx = sslCtx;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() {
|
||||
// Create a default pipeline implementation.
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
// Uncomment the following line if you want HTTPS
|
||||
//SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
|
||||
//engine.setUseClientMode(false);
|
||||
//pipeline.addLast("ssl", new SslHandler(engine));
|
||||
|
||||
if (sslCtx != null) {
|
||||
pipeline.addLast("ssl", sslCtx.newHandler());
|
||||
}
|
||||
pipeline.addLast("decoder", new HttpRequestDecoder());
|
||||
// Uncomment the following line if you don't want to handle HttpChunks.
|
||||
//pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
|
||||
|
@ -36,17 +36,14 @@ import java.util.concurrent.Executors;
|
||||
* A simple HTTP client that prints out the content of the HTTP response to
|
||||
* {@link System#out} to test {@link HttpSnoopServer}.
|
||||
*/
|
||||
public class HttpSnoopClient {
|
||||
public final class HttpSnoopClient {
|
||||
|
||||
private final URI uri;
|
||||
static final String URL = System.getProperty("url", "http://127.0.0.1:8080/");
|
||||
|
||||
public HttpSnoopClient(URI uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
public static void main(String[] args) throws Exception {
|
||||
URI uri = new URI(URL);
|
||||
String scheme = uri.getScheme() == null? "http" : uri.getScheme();
|
||||
String host = uri.getHost() == null? "localhost" : uri.getHost();
|
||||
String host = uri.getHost() == null? "127.0.0.1" : uri.getHost();
|
||||
int port = uri.getPort();
|
||||
if (port == -1) {
|
||||
if ("http".equalsIgnoreCase(scheme)) {
|
||||
@ -76,52 +73,37 @@ public class HttpSnoopClient {
|
||||
Executors.newCachedThreadPool(),
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
// Set up the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new HttpSnoopClientPipelineFactory(sslCtx));
|
||||
try {
|
||||
// Set up the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new HttpSnoopClientPipelineFactory(sslCtx, host, port));
|
||||
|
||||
// Start the connection attempt.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
|
||||
// Start the connection attempt.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
|
||||
|
||||
// Wait until the connection attempt succeeds or fails.
|
||||
Channel channel = future.awaitUninterruptibly().getChannel();
|
||||
if (!future.isSuccess()) {
|
||||
future.getCause().printStackTrace();
|
||||
// Wait until the connection attempt succeeds or fails.
|
||||
Channel channel = future.sync().getChannel();
|
||||
|
||||
// Prepare the HTTP request.
|
||||
HttpRequest request = new DefaultHttpRequest(
|
||||
HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath());
|
||||
request.headers().set(HttpHeaders.Names.HOST, host);
|
||||
request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
|
||||
request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);
|
||||
|
||||
// Set some example cookies.
|
||||
CookieEncoder httpCookieEncoder = new CookieEncoder(false);
|
||||
httpCookieEncoder.addCookie("my-cookie", "foo");
|
||||
httpCookieEncoder.addCookie("another-cookie", "bar");
|
||||
request.headers().set(HttpHeaders.Names.COOKIE, httpCookieEncoder.encode());
|
||||
|
||||
// Send the HTTP request.
|
||||
channel.write(request);
|
||||
|
||||
// Wait for the server to close the connection.
|
||||
channel.getCloseFuture().sync();
|
||||
} finally {
|
||||
// Shut down executor threads to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare the HTTP request.
|
||||
HttpRequest request = new DefaultHttpRequest(
|
||||
HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath());
|
||||
request.headers().set(HttpHeaders.Names.HOST, host);
|
||||
request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
|
||||
request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);
|
||||
|
||||
// Set some example cookies.
|
||||
CookieEncoder httpCookieEncoder = new CookieEncoder(false);
|
||||
httpCookieEncoder.addCookie("my-cookie", "foo");
|
||||
httpCookieEncoder.addCookie("another-cookie", "bar");
|
||||
request.headers().set(HttpHeaders.Names.COOKIE, httpCookieEncoder.encode());
|
||||
|
||||
// Send the HTTP request.
|
||||
channel.write(request);
|
||||
|
||||
// Wait for the server to close the connection.
|
||||
channel.getCloseFuture().awaitUninterruptibly();
|
||||
|
||||
// Shut down executor threads to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length != 1) {
|
||||
System.err.println(
|
||||
"Usage: " + HttpSnoopClient.class.getSimpleName() +
|
||||
" <URL>");
|
||||
return;
|
||||
}
|
||||
|
||||
URI uri = new URI(args[0]);
|
||||
new HttpSnoopClient(uri).run();
|
||||
}
|
||||
}
|
||||
|
@ -28,42 +28,42 @@ public class HttpSnoopClientHandler extends SimpleChannelUpstreamHandler {
|
||||
private boolean readingChunks;
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
if (!readingChunks) {
|
||||
HttpResponse response = (HttpResponse) e.getMessage();
|
||||
|
||||
System.out.println("STATUS: " + response.getStatus());
|
||||
System.out.println("VERSION: " + response.getProtocolVersion());
|
||||
System.out.println();
|
||||
System.err.println("STATUS: " + response.getStatus());
|
||||
System.err.println("VERSION: " + response.getProtocolVersion());
|
||||
System.err.println();
|
||||
|
||||
if (!response.headers().names().isEmpty()) {
|
||||
for (String name: response.headers().names()) {
|
||||
for (String value: response.headers().getAll(name)) {
|
||||
System.out.println("HEADER: " + name + " = " + value);
|
||||
System.err.println("HEADER: " + name + " = " + value);
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
System.err.println();
|
||||
}
|
||||
|
||||
if (response.isChunked()) {
|
||||
readingChunks = true;
|
||||
System.out.println("CHUNKED CONTENT {");
|
||||
System.err.println("CHUNKED CONTENT {");
|
||||
} else {
|
||||
ChannelBuffer content = response.getContent();
|
||||
if (content.readable()) {
|
||||
System.out.println("CONTENT {");
|
||||
System.out.println(content.toString(CharsetUtil.UTF_8));
|
||||
System.out.println("} END OF CONTENT");
|
||||
System.err.println("CONTENT {");
|
||||
System.err.println(content.toString(CharsetUtil.UTF_8));
|
||||
System.err.println("} END OF CONTENT");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
HttpChunk chunk = (HttpChunk) e.getMessage();
|
||||
if (chunk.isLast()) {
|
||||
readingChunks = false;
|
||||
System.out.println("} END OF CHUNKED CONTENT");
|
||||
System.err.println("} END OF CHUNKED CONTENT");
|
||||
} else {
|
||||
System.out.print(chunk.getContent().toString(CharsetUtil.UTF_8));
|
||||
System.out.flush();
|
||||
System.err.print(chunk.getContent().toString(CharsetUtil.UTF_8));
|
||||
System.err.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,18 +26,22 @@ import static org.jboss.netty.channel.Channels.*;
|
||||
public class HttpSnoopClientPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
private final SslContext sslCtx;
|
||||
private final String host;
|
||||
private final int port;
|
||||
|
||||
public HttpSnoopClientPipelineFactory(SslContext sslCtx) {
|
||||
public HttpSnoopClientPipelineFactory(SslContext sslCtx, String host, int port) {
|
||||
this.sslCtx = sslCtx;
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
public ChannelPipeline getPipeline() {
|
||||
// Create a default pipeline implementation.
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
// Enable HTTPS if necessary.
|
||||
if (sslCtx != null) {
|
||||
pipeline.addLast("ssl", sslCtx.newHandler());
|
||||
pipeline.addLast("ssl", sslCtx.newHandler(host, port));
|
||||
}
|
||||
|
||||
pipeline.addLast("codec", new HttpClientCodec());
|
||||
|
@ -17,6 +17,8 @@ package org.jboss.netty.example.http.snoop;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
@ -25,15 +27,21 @@ import java.util.concurrent.Executors;
|
||||
* An HTTP server that sends back the content of the received HTTP request
|
||||
* in a pretty plaintext form.
|
||||
*/
|
||||
public class HttpSnoopServer {
|
||||
public final class HttpSnoopServer {
|
||||
|
||||
private final int port;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
|
||||
|
||||
public HttpSnoopServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
||||
new NioServerSocketChannelFactory(
|
||||
@ -44,20 +52,9 @@ public class HttpSnoopServer {
|
||||
bootstrap.setOption("child.tcpNoDelay", true);
|
||||
|
||||
// Set up the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new HttpSnoopServerPipelineFactory());
|
||||
bootstrap.setPipelineFactory(new HttpSnoopServerPipelineFactory(sslCtx));
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
bootstrap.bind(new InetSocketAddress(PORT));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
new HttpSnoopServer(port).run();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,16 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.http.snoop;
|
||||
|
||||
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpVersion.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
@ -45,6 +35,16 @@ import org.jboss.netty.handler.codec.http.HttpResponse;
|
||||
import org.jboss.netty.handler.codec.http.QueryStringDecoder;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpVersion.*;
|
||||
|
||||
public class HttpSnoopServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private HttpRequest request;
|
||||
@ -53,7 +53,7 @@ public class HttpSnoopServerHandler extends SimpleChannelUpstreamHandler {
|
||||
private final StringBuilder buf = new StringBuilder();
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
if (!readingChunks) {
|
||||
HttpRequest request = this.request = (HttpRequest) e.getMessage();
|
||||
|
||||
@ -174,8 +174,7 @@ public class HttpSnoopServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
||||
throws Exception {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
@ -15,24 +15,30 @@
|
||||
*/
|
||||
package org.jboss.netty.example.http.snoop;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.handler.codec.http.HttpContentCompressor;
|
||||
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
|
||||
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
public class HttpSnoopServerPipelineFactory implements ChannelPipelineFactory {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
|
||||
private final SslContext sslCtx;
|
||||
|
||||
public HttpSnoopServerPipelineFactory(SslContext sslCtx) {
|
||||
this.sslCtx = sslCtx;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() {
|
||||
// Create a default pipeline implementation.
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
// Uncomment the following line if you want HTTPS
|
||||
//SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
|
||||
//engine.setUseClientMode(false);
|
||||
//pipeline.addLast("ssl", new SslHandler(engine));
|
||||
|
||||
if (sslCtx != null) {
|
||||
pipeline.addLast("ssl", sslCtx.newHandler());
|
||||
}
|
||||
pipeline.addLast("decoder", new HttpRequestDecoder());
|
||||
// Uncomment the following line if you don't want to handle HttpChunks.
|
||||
//pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
|
||||
|
@ -41,88 +41,81 @@ import java.util.concurrent.Executors;
|
||||
* for the detailed instruction on how to deploy the server-side HTTP tunnel in
|
||||
* your Servlet container.
|
||||
*/
|
||||
public class HttpTunnelingClientExample {
|
||||
public final class HttpTunnelingClientExample {
|
||||
|
||||
private final URI uri;
|
||||
static final String URL = System.getProperty("url", "http://localhost:8080/netty-tunnel");
|
||||
|
||||
public HttpTunnelingClientExample(URI uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
public static void main(String[] args) throws Exception {
|
||||
URI uri = new URI(URL);
|
||||
String scheme = uri.getScheme() == null? "http" : uri.getScheme();
|
||||
String host = uri.getHost() == null? "127.0.0.1" : uri.getHost();
|
||||
int port = uri.getPort();
|
||||
if (port == -1) {
|
||||
if ("http".equalsIgnoreCase(scheme)) {
|
||||
port = 80;
|
||||
} else if ("https".equalsIgnoreCase(scheme)) {
|
||||
port = 443;
|
||||
}
|
||||
}
|
||||
|
||||
if (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme)) {
|
||||
System.err.println("Only HTTP(S) is supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Configure the client.
|
||||
ClientBootstrap b = new ClientBootstrap(
|
||||
new HttpTunnelingClientSocketChannelFactory(
|
||||
new OioClientSocketChannelFactory(Executors.newCachedThreadPool())));
|
||||
|
||||
b.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
return Channels.pipeline(
|
||||
new StringDecoder(),
|
||||
new StringEncoder(),
|
||||
new LoggingHandler(InternalLogLevel.INFO));
|
||||
}
|
||||
});
|
||||
try {
|
||||
b.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() {
|
||||
return Channels.pipeline(
|
||||
new StringDecoder(),
|
||||
new StringEncoder(),
|
||||
new LoggingHandler(InternalLogLevel.INFO));
|
||||
}
|
||||
});
|
||||
|
||||
// Set additional options required by the HTTP tunneling transport.
|
||||
b.setOption("serverName", uri.getHost());
|
||||
b.setOption("serverPath", uri.getRawPath());
|
||||
// Set additional options required by the HTTP tunneling transport.
|
||||
b.setOption("serverName", uri.getHost());
|
||||
b.setOption("serverPath", uri.getRawPath());
|
||||
|
||||
// Configure SSL if necessary
|
||||
if ("https".equals(scheme)) {
|
||||
b.setOption("sslContext", new JdkSslClientContext(InsecureTrustManagerFactory.INSTANCE).context());
|
||||
} else if (!"http".equals(scheme)) {
|
||||
// Only HTTP and HTTPS are supported.
|
||||
System.err.println("Only HTTP(S) is supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make the connection attempt.
|
||||
ChannelFuture channelFuture = b.connect(
|
||||
new InetSocketAddress(uri.getHost(), uri.getPort()));
|
||||
channelFuture.awaitUninterruptibly();
|
||||
|
||||
// Read commands from the stdin.
|
||||
System.out.println("Enter text ('quit' to exit)");
|
||||
ChannelFuture lastWriteFuture = null;
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||
for (; ;) {
|
||||
String line = in.readLine();
|
||||
if (line == null || "quit".equalsIgnoreCase(line)) {
|
||||
break;
|
||||
// Configure SSL if necessary
|
||||
if ("https".equals(scheme)) {
|
||||
b.setOption("sslContext", new JdkSslClientContext(InsecureTrustManagerFactory.INSTANCE).context());
|
||||
}
|
||||
|
||||
// Sends the received line to the server.
|
||||
lastWriteFuture = channelFuture.getChannel().write(line);
|
||||
// Make the connection attempt.
|
||||
ChannelFuture channelFuture = b.connect(new InetSocketAddress(host, port));
|
||||
channelFuture.sync();
|
||||
|
||||
// Read commands from the stdin.
|
||||
System.err.println("Enter text ('quit' to exit)");
|
||||
|
||||
ChannelFuture lastWriteFuture = null;
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||
for (;;) {
|
||||
String line = in.readLine();
|
||||
if (line == null || "quit".equalsIgnoreCase(line)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Sends the received line to the server.
|
||||
lastWriteFuture = channelFuture.getChannel().write(line);
|
||||
}
|
||||
|
||||
// Wait until all messages are flushed before closing the channel.
|
||||
if (lastWriteFuture != null) {
|
||||
lastWriteFuture.sync();
|
||||
}
|
||||
|
||||
// Close the connection.
|
||||
channelFuture.getChannel().close().sync();
|
||||
} finally {
|
||||
// Shut down all threads.
|
||||
b.releaseExternalResources();
|
||||
}
|
||||
|
||||
// Wait until all messages are flushed before closing the channel.
|
||||
if (lastWriteFuture != null) {
|
||||
lastWriteFuture.awaitUninterruptibly();
|
||||
}
|
||||
|
||||
channelFuture.getChannel().close();
|
||||
// Wait until the connection is closed or the connection attempt fails.
|
||||
channelFuture.getChannel().getCloseFuture().awaitUninterruptibly();
|
||||
|
||||
// Shut down all threads.
|
||||
b.releaseExternalResources();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length != 1) {
|
||||
System.err.println(
|
||||
"Usage: " + HttpTunnelingClientExample.class.getSimpleName() +
|
||||
" <URL>");
|
||||
System.err.println(
|
||||
"Example: " + HttpTunnelingClientExample.class.getSimpleName() +
|
||||
" http://localhost:8080/netty-tunnel");
|
||||
return;
|
||||
}
|
||||
|
||||
URI uri = new URI(args[0]);
|
||||
new HttpTunnelingClientExample(uri).run();
|
||||
}
|
||||
}
|
||||
|
@ -31,54 +31,38 @@ import org.jboss.netty.handler.codec.http.multipart.DiskAttribute;
|
||||
import org.jboss.netty.handler.codec.http.multipart.DiskFileUpload;
|
||||
import org.jboss.netty.handler.codec.http.multipart.HttpDataFactory;
|
||||
import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestEncoder;
|
||||
import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestEncoder.ErrorDataEncoderException;
|
||||
import org.jboss.netty.handler.codec.http.multipart.InterfaceHttpData;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class HttpUploadClient {
|
||||
public final class HttpUploadClient {
|
||||
|
||||
private static final InternalLogger logger =
|
||||
InternalLoggerFactory.getInstance(HttpUploadClient.class);
|
||||
static final String BASE_URL = System.getProperty("baseUrl", "http://127.0.0.1:8080/");
|
||||
static final String FILE = System.getProperty("file", "upload.txt");
|
||||
|
||||
private final String baseUri;
|
||||
private final String filePath;
|
||||
|
||||
public HttpUploadClient(String baseUri, String filePath) {
|
||||
this.baseUri = baseUri;
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String postSimple, postFile, get;
|
||||
if (baseUri.endsWith("/")) {
|
||||
postSimple = baseUri + "formpost";
|
||||
postFile = baseUri + "formpostmultipart";
|
||||
get = baseUri + "formget";
|
||||
if (BASE_URL.endsWith("/")) {
|
||||
postSimple = BASE_URL + "formpost";
|
||||
postFile = BASE_URL + "formpostmultipart";
|
||||
get = BASE_URL + "formget";
|
||||
} else {
|
||||
postSimple = baseUri + "/formpost";
|
||||
postFile = baseUri + "/formpostmultipart";
|
||||
get = baseUri + "/formget";
|
||||
}
|
||||
URI uriSimple;
|
||||
try {
|
||||
uriSimple = new URI(postSimple);
|
||||
} catch (URISyntaxException e) {
|
||||
logger.error("Invalid URI syntax" + e.getCause());
|
||||
return;
|
||||
postSimple = BASE_URL + "/formpost";
|
||||
postFile = BASE_URL + "/formpostmultipart";
|
||||
get = BASE_URL + "/formget";
|
||||
}
|
||||
|
||||
URI uriSimple = new URI(postSimple);
|
||||
String scheme = uriSimple.getScheme() == null? "http" : uriSimple.getScheme();
|
||||
String host = uriSimple.getHost() == null? "localhost" : uriSimple.getHost();
|
||||
String host = uriSimple.getHost() == null? "127.0.0.1" : uriSimple.getHost();
|
||||
int port = uriSimple.getPort();
|
||||
if (port == -1) {
|
||||
if ("http".equalsIgnoreCase(scheme)) {
|
||||
@ -89,7 +73,7 @@ public class HttpUploadClient {
|
||||
}
|
||||
|
||||
if (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme)) {
|
||||
logger.error("Only HTTP(S) is supported.");
|
||||
System.err.println("Only HTTP(S) is supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -102,17 +86,10 @@ public class HttpUploadClient {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
URI uriFile;
|
||||
try {
|
||||
uriFile = new URI(postFile);
|
||||
} catch (URISyntaxException e) {
|
||||
logger.error("Error: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
File file = new File(filePath);
|
||||
if (! file.canRead()) {
|
||||
logger.error("A correct path is needed");
|
||||
return;
|
||||
URI uriFile = new URI(postFile);
|
||||
File file = new File(FILE);
|
||||
if (!file.canRead()) {
|
||||
throw new FileNotFoundException(FILE);
|
||||
}
|
||||
|
||||
// Configure the client.
|
||||
@ -121,58 +98,50 @@ public class HttpUploadClient {
|
||||
Executors.newCachedThreadPool(),
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
// Set up the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new HttpUploadClientPipelineFactory(sslCtx));
|
||||
// Set up the factory: here using a mixed memory/disk based on size threshold
|
||||
HttpDataFactory factory =
|
||||
new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE); // Disk if size exceed MINSIZE
|
||||
|
||||
// setup the factory: here using a mixed memory/disk based on size threshold
|
||||
HttpDataFactory factory = new DefaultHttpDataFactory(
|
||||
DefaultHttpDataFactory.MINSIZE); // Disk if size exceed MINSIZE
|
||||
DiskFileUpload.deleteOnExitTemporaryFile = true; // should delete file on exit (in normal exit)
|
||||
DiskFileUpload.baseDirectory = null; // system temp directory
|
||||
DiskAttribute.deleteOnExitTemporaryFile = true; // should delete file on exit (in normal exit)
|
||||
DiskAttribute.baseDirectory = null; // system temp directory
|
||||
try {
|
||||
// Set up the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new HttpUploadClientPipelineFactory(sslCtx, host, port));
|
||||
|
||||
// Simple Get form: no factory used (not usable)
|
||||
List<Entry<String, String>> headers =
|
||||
formget(bootstrap, host, port, get, uriSimple);
|
||||
if (headers == null) {
|
||||
DiskFileUpload.deleteOnExitTemporaryFile = true; // should delete file on exit (in normal exit)
|
||||
DiskFileUpload.baseDirectory = null; // system temp directory
|
||||
DiskAttribute.deleteOnExitTemporaryFile = true; // should delete file on exit (in normal exit)
|
||||
DiskAttribute.baseDirectory = null; // system temp directory
|
||||
|
||||
// Simple Get form: no factory used (not usable)
|
||||
List<Entry<String, String>> headers = formget(bootstrap, host, port, get, uriSimple);
|
||||
|
||||
// Simple Post form: factory used for big attributes
|
||||
List<InterfaceHttpData> bodylist = formpost(bootstrap, host, port, uriSimple, file, factory, headers);
|
||||
|
||||
// Multipart Post form: factory used
|
||||
formpostmultipart(bootstrap, host, port, uriFile, factory, headers, bodylist);
|
||||
} finally {
|
||||
// Shut down executor threads to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
// Really clean all temporary files if they still exist
|
||||
factory.cleanAllHttpDatas();
|
||||
return;
|
||||
}
|
||||
// Simple Post form: factory used for big attributes
|
||||
List<InterfaceHttpData> bodylist =
|
||||
formpost(bootstrap, host, port, uriSimple, file, factory, headers);
|
||||
if (bodylist == null) {
|
||||
factory.cleanAllHttpDatas();
|
||||
return;
|
||||
}
|
||||
// Multipart Post form: factory used
|
||||
formpostmultipart(bootstrap, host, port, uriFile, factory, headers, bodylist);
|
||||
|
||||
// Shut down executor threads to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
// Really clean all temporary files if they still exist
|
||||
factory.cleanAllHttpDatas();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard usage of HTTP API in Netty without file Upload (get is not able to achieve File upload
|
||||
* due to limitation on request size).
|
||||
*
|
||||
* @return the list of headers that will be used in every example after
|
||||
**/
|
||||
private static List<Entry<String, String>> formget(ClientBootstrap bootstrap, String host, int port, String get,
|
||||
URI uriSimple) {
|
||||
private static List<Entry<String, String>> formget(
|
||||
ClientBootstrap bootstrap, String host, int port, String get, URI uriSimple) throws Exception {
|
||||
// XXX /formget
|
||||
// No use of HttpPostRequestEncoder since not a POST
|
||||
// Start the connection attempt.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
|
||||
|
||||
// Wait until the connection attempt succeeds or fails.
|
||||
Channel channel = future.awaitUninterruptibly().getChannel();
|
||||
if (!future.isSuccess()) {
|
||||
future.getCause().printStackTrace();
|
||||
bootstrap.releaseExternalResources();
|
||||
return null;
|
||||
}
|
||||
Channel channel = future.sync().getChannel();
|
||||
|
||||
// Prepare the HTTP request.
|
||||
QueryStringEncoder encoder = new QueryStringEncoder(get);
|
||||
@ -185,28 +154,22 @@ public class HttpUploadClient {
|
||||
encoder.addParam("thirdinfo", "third value\r\ntest second line\r\n\r\nnew line\r\n");
|
||||
encoder.addParam("Send", "Send");
|
||||
|
||||
URI uriGet;
|
||||
try {
|
||||
uriGet = new URI(encoder.toString());
|
||||
} catch (URISyntaxException e) {
|
||||
logger.error("Error: " + e.getMessage());
|
||||
bootstrap.releaseExternalResources();
|
||||
return null;
|
||||
}
|
||||
|
||||
HttpRequest request = new DefaultHttpRequest(
|
||||
HttpVersion.HTTP_1_1, HttpMethod.GET, uriGet.toASCIIString());
|
||||
URI uriGet = new URI(encoder.toString());
|
||||
HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uriGet.toASCIIString());
|
||||
request.headers().set(HttpHeaders.Names.HOST, host);
|
||||
request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
|
||||
request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP + ',' +
|
||||
HttpHeaders.Values.DEFLATE);
|
||||
request.headers().set(
|
||||
HttpHeaders.Names.ACCEPT_ENCODING,
|
||||
HttpHeaders.Values.GZIP + ',' + HttpHeaders.Values.DEFLATE);
|
||||
|
||||
request.headers().set(HttpHeaders.Names.ACCEPT_CHARSET, "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
|
||||
request.headers().set(HttpHeaders.Names.ACCEPT_LANGUAGE, "fr");
|
||||
request.headers().set(HttpHeaders.Names.REFERER, uriSimple.toString());
|
||||
request.headers().set(HttpHeaders.Names.USER_AGENT, "Netty Simple Http Client side");
|
||||
request.headers().set(HttpHeaders.Names.ACCEPT,
|
||||
request.headers().set(
|
||||
HttpHeaders.Names.ACCEPT,
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
||||
|
||||
//connection will not close but needed
|
||||
// request.headers().set("Connection","keep-alive");
|
||||
// request.headers().set("Keep-Alive","300");
|
||||
@ -221,7 +184,7 @@ public class HttpUploadClient {
|
||||
channel.write(request);
|
||||
|
||||
// Wait for the server to close the connection.
|
||||
channel.getCloseFuture().awaitUninterruptibly();
|
||||
channel.getCloseFuture().sync();
|
||||
|
||||
return headers;
|
||||
}
|
||||
@ -231,24 +194,18 @@ public class HttpUploadClient {
|
||||
*
|
||||
* @return the list of HttpData object (attribute and file) to be reused on next post
|
||||
*/
|
||||
private static List<InterfaceHttpData> formpost(ClientBootstrap bootstrap,
|
||||
String host, int port,
|
||||
URI uriSimple, File file, HttpDataFactory factory,
|
||||
List<Entry<String, String>> headers) throws ErrorDataEncoderException {
|
||||
private static List<InterfaceHttpData> formpost(
|
||||
ClientBootstrap bootstrap,
|
||||
String host, int port, URI uriSimple, File file, HttpDataFactory factory,
|
||||
List<Entry<String, String>> headers) throws Exception {
|
||||
// XXX /formpost
|
||||
// Start the connection attempt.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
|
||||
// Wait until the connection attempt succeeds or fails.
|
||||
Channel channel = future.awaitUninterruptibly().getChannel();
|
||||
if (!future.isSuccess()) {
|
||||
future.getCause().printStackTrace();
|
||||
bootstrap.releaseExternalResources();
|
||||
return null;
|
||||
}
|
||||
Channel channel = future.sync().getChannel();
|
||||
|
||||
// Prepare the HTTP request.
|
||||
HttpRequest request = new DefaultHttpRequest(
|
||||
HttpVersion.HTTP_1_1, HttpMethod.POST, uriSimple.toASCIIString());
|
||||
HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, uriSimple.toASCIIString());
|
||||
|
||||
// Use the PostBody encoder
|
||||
HttpPostRequestEncoder bodyRequestEncoder =
|
||||
@ -264,6 +221,7 @@ public class HttpUploadClient {
|
||||
bodyRequestEncoder.addBodyAttribute("info", "first value");
|
||||
bodyRequestEncoder.addBodyAttribute("secondinfo", "secondvalue <20><><EFBFBD>&");
|
||||
bodyRequestEncoder.addBodyAttribute("thirdinfo", textArea);
|
||||
bodyRequestEncoder.addBodyAttribute("fourthinfo", textAreaLong);
|
||||
bodyRequestEncoder.addBodyFileUpload("myfile", file, "application/x-zip-compressed", false);
|
||||
|
||||
// finalize request
|
||||
@ -278,7 +236,7 @@ public class HttpUploadClient {
|
||||
// test if request was chunked and if so, finish the write
|
||||
if (bodyRequestEncoder.isChunked()) { // could do either request.isChunked()
|
||||
// either do it through ChunkedWriteHandler
|
||||
channel.write(bodyRequestEncoder).awaitUninterruptibly();
|
||||
channel.write(bodyRequestEncoder).sync();
|
||||
}
|
||||
|
||||
// Do not clear here since we will reuse the InterfaceHttpData on the next request
|
||||
@ -289,30 +247,24 @@ public class HttpUploadClient {
|
||||
// bodyRequestEncoder.cleanFiles();
|
||||
|
||||
// Wait for the server to close the connection.
|
||||
channel.getCloseFuture().awaitUninterruptibly();
|
||||
channel.getCloseFuture().sync();
|
||||
return bodylist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multipart example
|
||||
*/
|
||||
private static void formpostmultipart(ClientBootstrap bootstrap, String host, int port,
|
||||
URI uriFile, HttpDataFactory factory,
|
||||
List<Entry<String, String>> headers, List<InterfaceHttpData> bodylist) throws ErrorDataEncoderException {
|
||||
private static void formpostmultipart(
|
||||
ClientBootstrap bootstrap, String host, int port, URI uriFile, HttpDataFactory factory,
|
||||
List<Entry<String, String>> headers, List<InterfaceHttpData> bodylist) throws Exception {
|
||||
// XXX /formpostmultipart
|
||||
// Start the connection attempt.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
|
||||
// Wait until the connection attempt succeeds or fails.
|
||||
Channel channel = future.awaitUninterruptibly().getChannel();
|
||||
if (!future.isSuccess()) {
|
||||
future.getCause().printStackTrace();
|
||||
bootstrap.releaseExternalResources();
|
||||
return;
|
||||
}
|
||||
Channel channel = future.sync().getChannel();
|
||||
|
||||
// Prepare the HTTP request.
|
||||
HttpRequest request = new DefaultHttpRequest(
|
||||
HttpVersion.HTTP_1_1, HttpMethod.POST, uriFile.toASCIIString());
|
||||
HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, uriFile.toASCIIString());
|
||||
|
||||
// Use the PostBody encoder
|
||||
HttpPostRequestEncoder bodyRequestEncoder =
|
||||
@ -334,28 +286,14 @@ public class HttpUploadClient {
|
||||
|
||||
// test if request was chunked and if so, finish the write
|
||||
if (bodyRequestEncoder.isChunked()) {
|
||||
channel.write(bodyRequestEncoder).awaitUninterruptibly();
|
||||
channel.write(bodyRequestEncoder).sync();
|
||||
}
|
||||
|
||||
// Now no more use of file representation (and list of HttpData)
|
||||
bodyRequestEncoder.cleanFiles();
|
||||
|
||||
// Wait for the server to close the connection.
|
||||
channel.getCloseFuture().awaitUninterruptibly();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length != 2) {
|
||||
logger.error(
|
||||
"Usage: " + HttpUploadClient.class.getSimpleName() +
|
||||
" baseURI filePath");
|
||||
return;
|
||||
}
|
||||
|
||||
String baseUri = args[0];
|
||||
String filePath = args[1];
|
||||
|
||||
new HttpUploadClient(baseUri, filePath).run();
|
||||
channel.getCloseFuture().sync();
|
||||
}
|
||||
|
||||
// use to simulate a small TEXTAREA field in a form
|
||||
|
@ -22,58 +22,52 @@ import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
import org.jboss.netty.handler.codec.http.HttpChunk;
|
||||
import org.jboss.netty.handler.codec.http.HttpResponse;
|
||||
import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
public class HttpUploadClientHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final InternalLogger logger =
|
||||
InternalLoggerFactory.getInstance(HttpUploadClientHandler.class);
|
||||
|
||||
private boolean readingChunks;
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
if (!readingChunks) {
|
||||
HttpResponse response = (HttpResponse) e.getMessage();
|
||||
|
||||
logger.info("STATUS: " + response.getStatus());
|
||||
logger.info("VERSION: " + response.getProtocolVersion());
|
||||
System.err.println("STATUS: " + response.getStatus());
|
||||
System.err.println("VERSION: " + response.getProtocolVersion());
|
||||
|
||||
if (!response.headers().names().isEmpty()) {
|
||||
for (String name: response.headers().names()) {
|
||||
for (String value: response.headers().getAll(name)) {
|
||||
logger.info("HEADER: " + name + " = " + value);
|
||||
System.err.println("HEADER: " + name + " = " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (response.getStatus().getCode() == 200 && response.isChunked()) {
|
||||
readingChunks = true;
|
||||
logger.info("CHUNKED CONTENT {");
|
||||
System.err.println("CHUNKED CONTENT {");
|
||||
} else {
|
||||
ChannelBuffer content = response.getContent();
|
||||
if (content.readable()) {
|
||||
logger.info("CONTENT {");
|
||||
logger.info(content.toString(CharsetUtil.UTF_8));
|
||||
logger.info("} END OF CONTENT");
|
||||
System.err.println("CONTENT {");
|
||||
System.err.println(content.toString(CharsetUtil.UTF_8));
|
||||
System.err.println("} END OF CONTENT");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
HttpChunk chunk = (HttpChunk) e.getMessage();
|
||||
if (chunk.isLast()) {
|
||||
readingChunks = false;
|
||||
logger.info("} END OF CHUNKED CONTENT");
|
||||
System.err.println("} END OF CHUNKED CONTENT");
|
||||
} else {
|
||||
logger.info(chunk.getContent().toString(CharsetUtil.UTF_8));
|
||||
System.err.println(chunk.getContent().toString(CharsetUtil.UTF_8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
||||
throws Exception {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
@ -26,19 +26,24 @@ import org.jboss.netty.handler.stream.ChunkedWriteHandler;
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
public class HttpUploadClientPipelineFactory implements ChannelPipelineFactory {
|
||||
private final SslContext sslCtx;
|
||||
|
||||
public HttpUploadClientPipelineFactory(SslContext sslCtx) {
|
||||
private final SslContext sslCtx;
|
||||
private final String host;
|
||||
private final int port;
|
||||
|
||||
public HttpUploadClientPipelineFactory(SslContext sslCtx, String host, int port) {
|
||||
this.sslCtx = sslCtx;
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
public ChannelPipeline getPipeline() {
|
||||
// Create a default pipeline implementation.
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
// Enable HTTPS if necessary.
|
||||
if (sslCtx != null) {
|
||||
SslHandler handler = sslCtx.newHandler();
|
||||
SslHandler handler = sslCtx.newHandler(host, port);
|
||||
handler.setIssueHandshake(true);
|
||||
pipeline.addLast("ssl", handler);
|
||||
}
|
||||
|
@ -23,19 +23,21 @@ import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class HttpUploadServer {
|
||||
public final class HttpUploadServer {
|
||||
|
||||
private static final boolean useSsl = false; // Set to true to enable SSL.
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
|
||||
|
||||
private final SslContext sslCtx;
|
||||
private final int port;
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public HttpUploadServer(SslContext sslCtx, int port) {
|
||||
this.sslCtx = sslCtx;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
||||
new NioServerSocketChannelFactory(
|
||||
@ -46,25 +48,6 @@ public class HttpUploadServer {
|
||||
bootstrap.setPipelineFactory(new HttpUploadServerPipelineFactory(sslCtx));
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
|
||||
SslContext sslCtx;
|
||||
if (useSsl) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
new HttpUploadServer(sslCtx, port).run();
|
||||
bootstrap.bind(new InetSocketAddress(PORT));
|
||||
}
|
||||
}
|
||||
|
@ -50,8 +50,6 @@ import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestDecoder.Incom
|
||||
import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException;
|
||||
import org.jboss.netty.handler.codec.http.multipart.InterfaceHttpData;
|
||||
import org.jboss.netty.handler.codec.http.multipart.InterfaceHttpData.HttpDataType;
|
||||
import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -64,19 +62,9 @@ import java.util.Set;
|
||||
|
||||
public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final InternalLogger logger =
|
||||
InternalLoggerFactory.getInstance(HttpUploadServerHandler.class);
|
||||
private static final HttpDataFactory factory =
|
||||
new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE); // Disk if size exceed MINSIZE
|
||||
|
||||
private HttpRequest request;
|
||||
|
||||
private boolean readingChunks;
|
||||
|
||||
private final StringBuilder responseContent = new StringBuilder();
|
||||
|
||||
private static final HttpDataFactory factory = new DefaultHttpDataFactory(
|
||||
DefaultHttpDataFactory.MINSIZE); // Disk if size exceed MINSIZE
|
||||
|
||||
private HttpPostRequestDecoder decoder;
|
||||
static {
|
||||
//To limit to roughly 5MB each attribute, including fileupload
|
||||
//factory.setMaxLimit(5000000);
|
||||
@ -89,9 +77,13 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
DiskAttribute.baseDirectory = null; // system temp directory
|
||||
}
|
||||
|
||||
private final StringBuilder responseContent = new StringBuilder();
|
||||
private HttpPostRequestDecoder decoder;
|
||||
private HttpRequest request;
|
||||
private boolean readingChunks;
|
||||
|
||||
@Override
|
||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
|
||||
throws Exception {
|
||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
if (decoder != null) {
|
||||
decoder.cleanFiles();
|
||||
}
|
||||
@ -116,18 +108,13 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
responseContent.setLength(0);
|
||||
responseContent.append("WELCOME TO THE WILD WILD WEB SERVER\r\n");
|
||||
responseContent.append("===================================\r\n");
|
||||
|
||||
responseContent.append("VERSION: " +
|
||||
request.getProtocolVersion().getText() + "\r\n");
|
||||
|
||||
responseContent.append("REQUEST_URI: " + request.getUri() +
|
||||
"\r\n\r\n");
|
||||
responseContent.append("VERSION: " + request.getProtocolVersion().getText() + "\r\n");
|
||||
responseContent.append("REQUEST_URI: " + request.getUri() + "\r\n\r\n");
|
||||
responseContent.append("\r\n\r\n");
|
||||
|
||||
// new method
|
||||
for (Entry<String, String> entry: request.headers()) {
|
||||
responseContent.append("HEADER: " + entry.getKey() + '=' +
|
||||
entry.getValue() + "\r\n");
|
||||
responseContent.append("HEADER: " + entry.getKey() + '=' + entry.getValue() + "\r\n");
|
||||
}
|
||||
responseContent.append("\r\n\r\n");
|
||||
|
||||
@ -141,14 +128,12 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
cookies = decoder.decode(value);
|
||||
}
|
||||
for (Cookie cookie: cookies) {
|
||||
responseContent.append("COOKIE: " + cookie.toString() + "\r\n");
|
||||
responseContent.append("COOKIE: " + cookie + "\r\n");
|
||||
}
|
||||
responseContent.append("\r\n\r\n");
|
||||
|
||||
QueryStringDecoder decoderQuery = new QueryStringDecoder(request
|
||||
.getUri());
|
||||
Map<String, List<String>> uriAttributes = decoderQuery
|
||||
.getParameters();
|
||||
QueryStringDecoder decoderQuery = new QueryStringDecoder(request.getUri());
|
||||
Map<String, List<String>> uriAttributes = decoderQuery.getParameters();
|
||||
for (Entry<String, List<String>> attr: uriAttributes.entrySet()) {
|
||||
for (String attrVal: attr.getValue()) {
|
||||
responseContent.append("URI: " + attr.getKey() + '=' + attrVal + "\r\n");
|
||||
@ -174,10 +159,8 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
responseContent.append("Is Chunked: " + request.isChunked() +
|
||||
"\r\n");
|
||||
responseContent.append("IsMultipart: " + decoder.isMultipart() +
|
||||
"\r\n");
|
||||
responseContent.append("Is Chunked: " + request.isChunked() + "\r\n");
|
||||
responseContent.append("IsMultipart: " + decoder.isMultipart() + "\r\n");
|
||||
if (request.isChunked()) {
|
||||
// Chunk version
|
||||
responseContent.append("Chunks: ");
|
||||
@ -185,8 +168,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
} else {
|
||||
// Not chunk version
|
||||
readHttpDataAllReceive(e.getChannel());
|
||||
responseContent
|
||||
.append("\r\n\r\nEND OF NOT CHUNKED CONTENT\r\n");
|
||||
responseContent.append("\r\n\r\nEND OF NOT CHUNKED CONTENT\r\n");
|
||||
writeResponse(e.getChannel());
|
||||
}
|
||||
} else {
|
||||
@ -249,8 +231,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
} catch (EndOfDataDecoderException e1) {
|
||||
// end
|
||||
responseContent
|
||||
.append("\r\n\r\nEND OF CONTENT CHUNK BY CHUNK\r\n\r\n");
|
||||
responseContent.append("\r\n\r\nEND OF CONTENT CHUNK BY CHUNK\r\n\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,17 +252,14 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
if (value.length() > 100) {
|
||||
responseContent.append("\r\nBODY Attribute: " +
|
||||
attribute.getHttpDataType().name() + ": " +
|
||||
attribute.getName() + " data too long\r\n");
|
||||
attribute.getHttpDataType().name() + ": " + attribute.getName() + " data too long\r\n");
|
||||
} else {
|
||||
responseContent.append("\r\nBODY Attribute: " +
|
||||
attribute.getHttpDataType().name() + ": " +
|
||||
attribute.toString() + "\r\n");
|
||||
responseContent.append(
|
||||
"\r\nBODY Attribute: " + attribute.getHttpDataType().name() + ": " + attribute + "\r\n");
|
||||
}
|
||||
} else {
|
||||
responseContent.append("\r\nBODY FileUpload: " +
|
||||
data.getHttpDataType().name() + ": " + data.toString() +
|
||||
"\r\n");
|
||||
responseContent.append(
|
||||
"\r\nBODY FileUpload: " + data.getHttpDataType().name() + ": " + data + "\r\n");
|
||||
if (data.getHttpDataType() == HttpDataType.FileUpload) {
|
||||
FileUpload fileUpload = (FileUpload) data;
|
||||
if (fileUpload.isCompleted()) {
|
||||
@ -295,9 +273,8 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
responseContent.append("\r\n");
|
||||
} else {
|
||||
responseContent
|
||||
.append("\tFile too long to be printed out:" +
|
||||
fileUpload.length() + "\r\n");
|
||||
responseContent.append(
|
||||
"\tFile too long to be printed out:" + fileUpload.length() + "\r\n");
|
||||
}
|
||||
// fileUpload.isInMemory();// tells if the file is in Memory
|
||||
// or on File
|
||||
@ -306,8 +283,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
// decoder.removeFileUploadFromClean(fileUpload); //remove
|
||||
// the File of to delete file
|
||||
} else {
|
||||
responseContent
|
||||
.append("\tFile to be continued but should not!\r\n");
|
||||
responseContent.append("\tFile to be continued but should not!\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -315,29 +291,24 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private void writeResponse(Channel channel) {
|
||||
// Convert the response content to a ChannelBuffer.
|
||||
ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent
|
||||
.toString(), CharsetUtil.UTF_8);
|
||||
ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent.toString(), CharsetUtil.UTF_8);
|
||||
responseContent.setLength(0);
|
||||
|
||||
// Decide whether to close the connection or not.
|
||||
boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request
|
||||
.headers().get(HttpHeaders.Names.CONNECTION)) ||
|
||||
boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(
|
||||
request.headers().get(HttpHeaders.Names.CONNECTION)) ||
|
||||
request.getProtocolVersion().equals(HttpVersion.HTTP_1_0) &&
|
||||
!HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request
|
||||
.headers().get(HttpHeaders.Names.CONNECTION));
|
||||
!HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request.headers().get(HttpHeaders.Names.CONNECTION));
|
||||
|
||||
// Build the response object.
|
||||
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1,
|
||||
HttpResponseStatus.OK);
|
||||
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
|
||||
response.setContent(buf);
|
||||
response.headers().set(HttpHeaders.Names.CONTENT_TYPE,
|
||||
"text/plain; charset=UTF-8");
|
||||
response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=UTF-8");
|
||||
|
||||
if (!close) {
|
||||
// There's no need to add 'Content-Length' header
|
||||
// if this is the last response.
|
||||
response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, String
|
||||
.valueOf(buf.readableBytes()));
|
||||
response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buf.readableBytes()));
|
||||
}
|
||||
|
||||
Set<Cookie> cookies;
|
||||
@ -353,8 +324,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
CookieEncoder cookieEncoder = new CookieEncoder(true);
|
||||
for (Cookie cookie: cookies) {
|
||||
cookieEncoder.addCookie(cookie);
|
||||
response.headers().add(HttpHeaders.Names.SET_COOKIE, cookieEncoder
|
||||
.encode());
|
||||
response.headers().add(HttpHeaders.Names.SET_COOKIE, cookieEncoder.encode());
|
||||
cookieEncoder = new CookieEncoder(true);
|
||||
}
|
||||
}
|
||||
@ -376,8 +346,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
responseContent.append("<head>");
|
||||
responseContent.append("<title>Netty Test Form</title>\r\n");
|
||||
responseContent.append("</head>\r\n");
|
||||
responseContent
|
||||
.append("<body bgcolor=white><style>td{font-size: 12pt;}</style>");
|
||||
responseContent.append("<body bgcolor=white><style>td{font-size: 12pt;}</style>");
|
||||
|
||||
responseContent.append("<table border=\"0\">");
|
||||
responseContent.append("<tr>");
|
||||
@ -389,98 +358,66 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
responseContent.append("</table>\r\n");
|
||||
|
||||
// GET
|
||||
responseContent
|
||||
.append("<CENTER>GET FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
|
||||
responseContent.append("<CENTER>GET FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
|
||||
responseContent.append("<FORM ACTION=\"/formget\" METHOD=\"GET\">");
|
||||
responseContent
|
||||
.append("<input type=hidden name=getform value=\"GET\">");
|
||||
responseContent.append("<input type=hidden name=getform value=\"GET\">");
|
||||
responseContent.append("<table border=\"0\">");
|
||||
responseContent
|
||||
.append("<tr><td>Fill with value: <br> <input type=text name=\"info\" size=10></td></tr>");
|
||||
responseContent
|
||||
.append("<tr><td>Fill with value: <br> <input type=text name=\"secondinfo\" size=20>");
|
||||
responseContent
|
||||
.append("<tr><td>Fill with value: <br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
|
||||
responseContent.append("<tr><td>Fill with value:<br> <input type=text name=\"info\" size=10></td></tr>");
|
||||
responseContent.append("<tr><td>Fill with value:<br> <input type=text name=\"secondinfo\" size=20>");
|
||||
responseContent.append("<tr><td>Fill with value:<br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
|
||||
responseContent.append("</td></tr>");
|
||||
responseContent
|
||||
.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
|
||||
responseContent
|
||||
.append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
|
||||
responseContent.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
|
||||
responseContent.append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
|
||||
responseContent.append("</table></FORM>\r\n");
|
||||
responseContent
|
||||
.append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
|
||||
responseContent.append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
|
||||
|
||||
// POST
|
||||
responseContent
|
||||
.append("<CENTER>POST FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
|
||||
responseContent.append("<CENTER>POST FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
|
||||
responseContent.append("<FORM ACTION=\"/formpost\" METHOD=\"POST\">");
|
||||
responseContent
|
||||
.append("<input type=hidden name=getform value=\"POST\">");
|
||||
responseContent.append("<input type=hidden name=getform value=\"POST\">");
|
||||
responseContent.append("<table border=\"0\">");
|
||||
responseContent
|
||||
.append("<tr><td>Fill with value: <br> <input type=text name=\"info\" size=10></td></tr>");
|
||||
responseContent
|
||||
.append("<tr><td>Fill with value: <br> <input type=text name=\"secondinfo\" size=20>");
|
||||
responseContent
|
||||
.append("<tr><td>Fill with value: <br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
|
||||
responseContent
|
||||
.append("<tr><td>Fill with file (only file name will be transmitted): <br> " +
|
||||
"<input type=file name=\"myfile\">");
|
||||
responseContent.append("<tr><td>Fill with value:<br> <input type=text name=\"info\" size=10></td></tr>");
|
||||
responseContent.append("<tr><td>Fill with value:<br> <input type=text name=\"secondinfo\" size=20>");
|
||||
responseContent.append("<tr><td>Fill with value:<br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
|
||||
responseContent.append("<tr><td>Fill with file (only file name will be transmitted): <br> ");
|
||||
responseContent.append("<input type=file name=\"myfile\">");
|
||||
responseContent.append("</td></tr>");
|
||||
responseContent
|
||||
.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
|
||||
responseContent
|
||||
.append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
|
||||
responseContent.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
|
||||
responseContent.append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
|
||||
responseContent.append("</table></FORM>\r\n");
|
||||
responseContent
|
||||
.append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
|
||||
responseContent.append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
|
||||
|
||||
// POST with enctype="multipart/form-data"
|
||||
responseContent
|
||||
.append("<CENTER>POST MULTIPART FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
|
||||
responseContent
|
||||
.append("<FORM ACTION=\"/formpostmultipart\" ENCTYPE=\"multipart/form-data\" METHOD=\"POST\">");
|
||||
responseContent
|
||||
.append("<input type=hidden name=getform value=\"POST\">");
|
||||
responseContent.append("<CENTER>POST MULTIPART FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
|
||||
responseContent.append("<FORM ACTION=\"/formpostmultipart\" ENCTYPE=\"multipart/form-data\" METHOD=\"POST\">");
|
||||
responseContent.append("<input type=hidden name=getform value=\"POST\">");
|
||||
responseContent.append("<table border=\"0\">");
|
||||
responseContent
|
||||
.append("<tr><td>Fill with value: <br> <input type=text name=\"info\" size=10></td></tr>");
|
||||
responseContent
|
||||
.append("<tr><td>Fill with value: <br> <input type=text name=\"secondinfo\" size=20>");
|
||||
responseContent
|
||||
.append("<tr><td>Fill with value: <br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
|
||||
responseContent
|
||||
.append("<tr><td>Fill with file: <br> <input type=file name=\"myfile\">");
|
||||
responseContent.append("<tr><td>Fill with value:<br> <input type=text name=\"info\" size=10></td></tr>");
|
||||
responseContent.append("<tr><td>Fill with value:<br> <input type=text name=\"secondinfo\" size=20>");
|
||||
responseContent.append("<tr><td>Fill with value:<br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
|
||||
responseContent.append("<tr><td>Fill with file: <br> <input type=file name=\"myfile\">");
|
||||
responseContent.append("</td></tr>");
|
||||
responseContent
|
||||
.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
|
||||
responseContent
|
||||
.append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
|
||||
responseContent.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
|
||||
responseContent.append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
|
||||
responseContent.append("</table></FORM>\r\n");
|
||||
responseContent
|
||||
.append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
|
||||
responseContent.append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
|
||||
|
||||
responseContent.append("</body>");
|
||||
responseContent.append("</html>");
|
||||
|
||||
ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent
|
||||
.toString(), CharsetUtil.UTF_8);
|
||||
ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent.toString(), CharsetUtil.UTF_8);
|
||||
// Build the response object.
|
||||
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1,
|
||||
HttpResponseStatus.OK);
|
||||
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
|
||||
response.setContent(buf);
|
||||
response.headers().set(HttpHeaders.Names.CONTENT_TYPE,
|
||||
"text/html; charset=UTF-8");
|
||||
response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buf
|
||||
.readableBytes()));
|
||||
response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/html; charset=UTF-8");
|
||||
response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buf.readableBytes()));
|
||||
// Write the response.
|
||||
e.getChannel().write(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
||||
throws Exception {
|
||||
logger.error(responseContent.toString(), e.getCause());
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public class HttpUploadServerPipelineFactory implements ChannelPipelineFactory {
|
||||
this.sslCtx = sslCtx;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
public ChannelPipeline getPipeline() {
|
||||
// Create a default pipeline implementation.
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
|
@ -15,25 +15,26 @@
|
||||
*/
|
||||
package org.jboss.netty.example.http.websocketx.autobahn;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* A Web Socket echo server for running the <a href="http://www.tavendo.de/autobahn/testsuite.html">autobahn</a> test
|
||||
* suite
|
||||
*/
|
||||
public class AutobahnServer {
|
||||
public final class AutobahnServer {
|
||||
|
||||
private final int port;
|
||||
public static void main(String[] args) {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 9000;
|
||||
}
|
||||
|
||||
public AutobahnServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
|
||||
Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
|
||||
@ -46,16 +47,6 @@ public class AutobahnServer {
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
|
||||
System.out.println("Web Socket Server started at port " + port);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 9000;
|
||||
}
|
||||
new AutobahnServer(port).run();
|
||||
System.err.println("Web Socket Server started at port " + port);
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.http.websocketx.autobahn;
|
||||
|
||||
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpMethod.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpVersion.*;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.ChannelFutureListener;
|
||||
@ -44,6 +39,11 @@ import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpMethod.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpVersion.*;
|
||||
|
||||
/**
|
||||
* Handles handshakes and messages
|
||||
*/
|
||||
@ -53,7 +53,7 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
|
||||
private WebSocketServerHandshaker handshaker;
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
Object msg = e.getMessage();
|
||||
if (msg instanceof HttpRequest) {
|
||||
handleHttpRequest(ctx, (HttpRequest) msg);
|
||||
@ -62,7 +62,7 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) throws Exception {
|
||||
private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) {
|
||||
// Allow only GET methods.
|
||||
if (req.getMethod() != GET) {
|
||||
sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN));
|
||||
@ -70,8 +70,8 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
// Handshake
|
||||
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
||||
getWebSocketLocation(req), null, false);
|
||||
WebSocketServerHandshakerFactory wsFactory =
|
||||
new WebSocketServerHandshakerFactory(getWebSocketLocation(req), null, false);
|
||||
handshaker = wsFactory.newHandshaker(req);
|
||||
if (handshaker == null) {
|
||||
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());
|
||||
@ -82,8 +82,8 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String
|
||||
.format("Channel %s received %s", ctx.getChannel().getId(), frame.getClass().getSimpleName()));
|
||||
logger.debug(String.format(
|
||||
"Channel %s received %s", ctx.getChannel().getId(), frame.getClass().getSimpleName()));
|
||||
}
|
||||
|
||||
if (frame instanceof CloseWebSocketFrame) {
|
||||
@ -124,7 +124,7 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
@ -15,18 +15,18 @@
|
||||
*/
|
||||
package org.jboss.netty.example.http.websocketx.autobahn;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
|
||||
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
|
||||
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class AutobahnServerPipelineFactory implements ChannelPipelineFactory {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
public ChannelPipeline getPipeline() {
|
||||
// Create a default pipeline implementation.
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
pipeline.addLast("decoder", new HttpRequestDecoder());
|
||||
|
@ -36,11 +36,6 @@
|
||||
//THE SOFTWARE.
|
||||
package org.jboss.netty.example.http.websocketx.client;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
@ -57,16 +52,53 @@ import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.WebSocketVersion;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
|
||||
public class WebSocketClient {
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
private final URI uri;
|
||||
public final class WebSocketClient {
|
||||
|
||||
public WebSocketClient(URI uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
static final String URL = System.getProperty("url", "ws://127.0.0.1:8080/websocket");
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
URI uri = new URI(URL);
|
||||
String scheme = uri.getScheme() == null? "http" : uri.getScheme();
|
||||
final String host = uri.getHost() == null? "127.0.0.1" : uri.getHost();
|
||||
final int port;
|
||||
if (uri.getPort() == -1) {
|
||||
if ("http".equalsIgnoreCase(scheme)) {
|
||||
port = 80;
|
||||
} else if ("https".equalsIgnoreCase(scheme)) {
|
||||
port = 443;
|
||||
} else {
|
||||
port = -1;
|
||||
}
|
||||
} else {
|
||||
port = uri.getPort();
|
||||
}
|
||||
|
||||
if (!"ws".equalsIgnoreCase(scheme) && !"wss".equalsIgnoreCase(scheme)) {
|
||||
System.err.println("Only WS(S) is supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean ssl = "wss".equalsIgnoreCase(scheme);
|
||||
final SslContext sslCtx;
|
||||
if (ssl) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
Map<String, String> customHeaders = new HashMap<String, String>();
|
||||
customHeaders.put("MyHeader", "MyValue");
|
||||
|
||||
public void run() throws Exception {
|
||||
ClientBootstrap bootstrap =
|
||||
new ClientBootstrap(
|
||||
new NioClientSocketChannelFactory(
|
||||
@ -74,16 +106,7 @@ public class WebSocketClient {
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
Channel ch = null;
|
||||
|
||||
try {
|
||||
String protocol = uri.getScheme();
|
||||
if (!"ws".equals(protocol)) {
|
||||
throw new IllegalArgumentException("Unsupported protocol: " + protocol);
|
||||
}
|
||||
|
||||
HashMap<String, String> customHeaders = new HashMap<String, String>();
|
||||
customHeaders.put("MyHeader", "MyValue");
|
||||
|
||||
// Connect with V13 (RFC 6455 aka HyBi-17). You can change it to V08 or V00.
|
||||
// If you change it to V00, ping is not supported and remember to change
|
||||
// HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline.
|
||||
@ -92,9 +115,12 @@ public class WebSocketClient {
|
||||
uri, WebSocketVersion.V13, null, false, customHeaders);
|
||||
|
||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline pipeline = Channels.pipeline();
|
||||
|
||||
if (sslCtx != null) {
|
||||
pipeline.addLast("ssl", sslCtx.newHandler(host, port));
|
||||
}
|
||||
pipeline.addLast("decoder", new HttpResponseDecoder());
|
||||
pipeline.addLast("encoder", new HttpRequestEncoder());
|
||||
pipeline.addLast("ws-handler", new WebSocketClientHandler(handshaker));
|
||||
@ -102,33 +128,26 @@ public class WebSocketClient {
|
||||
}
|
||||
});
|
||||
|
||||
// Connect
|
||||
System.out.println("WebSocket Client connecting");
|
||||
ChannelFuture future =
|
||||
bootstrap.connect(
|
||||
new InetSocketAddress(uri.getHost(), uri.getPort()));
|
||||
future.syncUninterruptibly();
|
||||
// Connect.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
|
||||
ch = future.sync().getChannel();
|
||||
|
||||
ch = future.getChannel();
|
||||
handshaker.handshake(ch).syncUninterruptibly();
|
||||
handshaker.handshake(ch).sync();
|
||||
|
||||
// Send 10 messages and wait for responses
|
||||
System.out.println("WebSocket Client sending message");
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
ch.write(new TextWebSocketFrame("Message #" + i));
|
||||
}
|
||||
|
||||
// Ping
|
||||
System.out.println("WebSocket Client sending ping");
|
||||
ch.write(new PingWebSocketFrame(ChannelBuffers.copiedBuffer(new byte[]{1, 2, 3, 4, 5, 6})));
|
||||
ch.write(new PingWebSocketFrame(ChannelBuffers.wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6 })));
|
||||
|
||||
// Close
|
||||
System.out.println("WebSocket Client sending close");
|
||||
ch.write(new CloseWebSocketFrame());
|
||||
|
||||
// WebSocketClientHandler will close the connection when the server
|
||||
// responds to the CloseWebSocketFrame.
|
||||
ch.getCloseFuture().awaitUninterruptibly();
|
||||
ch.getCloseFuture().sync();
|
||||
} finally {
|
||||
if (ch != null) {
|
||||
ch.close();
|
||||
@ -136,14 +155,4 @@ public class WebSocketClient {
|
||||
bootstrap.releaseExternalResources();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
URI uri;
|
||||
if (args.length > 0) {
|
||||
uri = new URI(args[0]);
|
||||
} else {
|
||||
uri = new URI("ws://localhost:8080/websocket");
|
||||
}
|
||||
new WebSocketClient(uri).run();
|
||||
}
|
||||
}
|
||||
|
@ -61,44 +61,44 @@ public class WebSocketClientHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
System.out.println("WebSocket Client disconnected!");
|
||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
System.err.println("WebSocket Client disconnected!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
Channel ch = ctx.getChannel();
|
||||
if (!handshaker.isHandshakeComplete()) {
|
||||
handshaker.finishHandshake(ch, (HttpResponse) e.getMessage());
|
||||
System.out.println("WebSocket Client connected!");
|
||||
System.err.println("WebSocket Client connected!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.getMessage() instanceof HttpResponse) {
|
||||
HttpResponse response = (HttpResponse) e.getMessage();
|
||||
throw new Exception("Unexpected HttpResponse (status=" + response.getStatus() + ", content="
|
||||
+ response.getContent().toString(CharsetUtil.UTF_8) + ')');
|
||||
throw new IllegalStateException(
|
||||
"unexpected response (status=" + response.getStatus() +
|
||||
", content=" + response.getContent().toString(CharsetUtil.UTF_8) + ')');
|
||||
}
|
||||
|
||||
WebSocketFrame frame = (WebSocketFrame) e.getMessage();
|
||||
if (frame instanceof TextWebSocketFrame) {
|
||||
TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
|
||||
System.out.println("WebSocket Client received message: " + textFrame.getText());
|
||||
System.err.println("WebSocket Client received message: " + textFrame.getText());
|
||||
} else if (frame instanceof PongWebSocketFrame) {
|
||||
System.out.println("WebSocket Client received pong");
|
||||
System.err.println("WebSocket Client received pong");
|
||||
} else if (frame instanceof CloseWebSocketFrame) {
|
||||
System.out.println("WebSocket Client received closing");
|
||||
System.err.println("WebSocket Client received closing");
|
||||
ch.close();
|
||||
} else if (frame instanceof PingWebSocketFrame) {
|
||||
System.out.println("WebSocket Client received ping, response with pong");
|
||||
System.err.println("WebSocket Client received ping, response with pong");
|
||||
ch.write(new PongWebSocketFrame(frame.getBinaryData()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
||||
final Throwable t = e.getCause();
|
||||
t.printStackTrace();
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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 org.jboss.netty.example.http.websocketx.html5;
|
||||
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelHandler;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
|
||||
public class CustomTextFrameHandler extends SimpleChannelHandler {
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
if (e.getMessage() instanceof TextWebSocketFrame) {
|
||||
TextWebSocketFrame frame = (TextWebSocketFrame) e.getMessage();
|
||||
ctx.getChannel().write(new TextWebSocketFrame(frame.getText().toUpperCase()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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 org.jboss.netty.example.http.websocketx.html5;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
import org.jboss.netty.example.http.websocketx.server.WebSocketServerPipelineFactory;
|
||||
|
||||
/**
|
||||
* A WebSocket Server that respondes to requests at:
|
||||
*
|
||||
* <pre>
|
||||
* http://localhost:8080/websocket
|
||||
* </pre>
|
||||
*
|
||||
* The example differs from many of the other examples in Netty in that is does
|
||||
* not have an acomponying client. Instead a html page is provided that
|
||||
* interacts with this server. <br>
|
||||
* Open up the following file a web browser that supports WebSocket's:
|
||||
*
|
||||
* <pre>
|
||||
* netty/src/test/resources/websocketx/html5/websocket.html
|
||||
* </pre>
|
||||
*
|
||||
* The html page is very simple were you simply enter some text and the server
|
||||
* will echo the same text back, but in uppercase. You, also see status messages
|
||||
* in the "Response From Server" area when client has connected, disconnected
|
||||
* etc.
|
||||
*
|
||||
*/
|
||||
public class WebSocketServer {
|
||||
|
||||
private final int port;
|
||||
|
||||
public WebSocketServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
|
||||
Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
|
||||
|
||||
// Set up the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new WebSocketServerPipelineFactory());
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
|
||||
System.out.println("Web socket server started at port " + port + '.');
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
new WebSocketServer(port).run();
|
||||
}
|
||||
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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 org.jboss.netty.example.http.websocketx.html5;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
|
||||
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
|
||||
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
|
||||
|
||||
public class WebSocketServerPipelineFactory implements ChannelPipelineFactory {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
// Create a default pipeline implementation.
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
pipeline.addLast("decoder", new HttpRequestDecoder());
|
||||
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
|
||||
pipeline.addLast("encoder", new HttpResponseEncoder());
|
||||
pipeline.addLast("handler", new WebSocketServerProtocolHandler("/websocket"));
|
||||
pipeline.addLast("testFramehandler", new CustomTextFrameHandler());
|
||||
return pipeline;
|
||||
}
|
||||
}
|
@ -15,11 +15,13 @@
|
||||
*/
|
||||
package org.jboss.netty.example.http.websocketx.server;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* A HTTP server which serves Web Socket requests at:
|
||||
@ -42,34 +44,30 @@ import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
*/
|
||||
public class WebSocketServer {
|
||||
|
||||
private final int port;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
|
||||
|
||||
public WebSocketServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
|
||||
Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
|
||||
|
||||
// Set up the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new WebSocketServerPipelineFactory());
|
||||
bootstrap.setPipelineFactory(new WebSocketServerPipelineFactory(sslCtx));
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
bootstrap.bind(new InetSocketAddress(PORT));
|
||||
|
||||
System.out.println("Web socket server started at port " + port + '.');
|
||||
System.out.println("Open your browser and navigate to http://localhost:" + port + '/');
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
new WebSocketServer(port).run();
|
||||
System.err.println("Web socket server started at port " + PORT + '.');
|
||||
System.err.println("Open your browser and navigate to http://localhost:" + PORT + '/');
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,6 @@ import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
|
||||
import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
|
||||
@ -47,14 +45,13 @@ import static org.jboss.netty.handler.codec.http.HttpVersion.*;
|
||||
* Handles handshakes and messages
|
||||
*/
|
||||
public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandler.class);
|
||||
|
||||
private static final String WEBSOCKET_PATH = "/websocket";
|
||||
|
||||
private WebSocketServerHandshaker handshaker;
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
Object msg = e.getMessage();
|
||||
if (msg instanceof HttpRequest) {
|
||||
handleHttpRequest(ctx, (HttpRequest) msg);
|
||||
@ -63,7 +60,7 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) throws Exception {
|
||||
private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) {
|
||||
// Allow only GET methods.
|
||||
if (req.getMethod() != GET) {
|
||||
sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN));
|
||||
@ -101,7 +98,6 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
|
||||
|
||||
// Check for closing frame
|
||||
if (frame instanceof CloseWebSocketFrame) {
|
||||
handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);
|
||||
@ -112,15 +108,13 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
||||
return;
|
||||
}
|
||||
if (!(frame instanceof TextWebSocketFrame)) {
|
||||
throw new UnsupportedOperationException(String.format("%s frame types not supported", frame.getClass()
|
||||
.getName()));
|
||||
throw new UnsupportedOperationException(
|
||||
String.format("%s frame types not supported", frame.getClass().getName()));
|
||||
}
|
||||
|
||||
// Send the uppercase string back.
|
||||
String request = ((TextWebSocketFrame) frame).getText();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Channel %s received %s", ctx.getChannel().getId(), request));
|
||||
}
|
||||
System.err.println(String.format("Channel %s received %s", ctx.getChannel().getId(), request));
|
||||
ctx.getChannel().write(new TextWebSocketFrame(request.toUpperCase()));
|
||||
}
|
||||
|
||||
@ -139,7 +133,7 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
@ -15,20 +15,29 @@
|
||||
*/
|
||||
package org.jboss.netty.example.http.websocketx.server;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.Channels;
|
||||
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
|
||||
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
|
||||
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class WebSocketServerPipelineFactory implements ChannelPipelineFactory {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
// Create a default pipeline implementation.
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
private final SslContext sslCtx;
|
||||
|
||||
public WebSocketServerPipelineFactory(SslContext sslCtx) {
|
||||
this.sslCtx = sslCtx;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline pipeline = Channels.pipeline();
|
||||
if (sslCtx != null) {
|
||||
pipeline.addLast("ssl", sslCtx.newHandler());
|
||||
}
|
||||
pipeline.addLast("decoder", new HttpRequestDecoder());
|
||||
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
|
||||
pipeline.addLast("encoder", new HttpResponseEncoder());
|
||||
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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 org.jboss.netty.example.http.websocketx.sslserver;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
|
||||
/**
|
||||
* A HTTP server which serves Web Socket requests at:
|
||||
*
|
||||
* https://localhost:8081/websocket
|
||||
*
|
||||
* Open your browser at https://localhost:8081/, then the demo page will be loaded and a Web Socket connection will be
|
||||
* made automatically.
|
||||
*
|
||||
* This server illustrates support for the different web socket specification versions and will work with:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Safari 5+ (draft-ietf-hybi-thewebsocketprotocol-00)
|
||||
* <li>Chrome 6-13 (draft-ietf-hybi-thewebsocketprotocol-00)
|
||||
* <li>Chrome 14+ (draft-ietf-hybi-thewebsocketprotocol-10)
|
||||
* <li>Chrome 16+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17)
|
||||
* <li>Firefox 7+ (draft-ietf-hybi-thewebsocketprotocol-10)
|
||||
* </ul>
|
||||
*/
|
||||
public class WebSocketSslServer {
|
||||
|
||||
private final int port;
|
||||
|
||||
public WebSocketSslServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
|
||||
Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
|
||||
|
||||
// Set up the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new WebSocketSslServerPipelineFactory());
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
|
||||
System.out.println("Web socket server started at port " + port + '.');
|
||||
System.out.println("Open your browser and navigate to https://localhost:" + port + '/');
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8443;
|
||||
}
|
||||
|
||||
String keyStoreFilePath = System.getProperty("keystore.file.path");
|
||||
if (keyStoreFilePath == null || keyStoreFilePath.length() == 0) {
|
||||
System.out.println("ERROR: System property keystore.file.path not set. Exiting now!");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
String keyStoreFilePassword = System.getProperty("keystore.file.password");
|
||||
if (keyStoreFilePassword == null || keyStoreFilePassword.length() == 0) {
|
||||
System.out.println("ERROR: System property keystore.file.password not set. Exiting now!");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
new WebSocketSslServer(port).run();
|
||||
}
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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 org.jboss.netty.example.http.websocketx.sslserver;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.ChannelFutureListener;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ExceptionEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
import org.jboss.netty.example.http.websocketx.server.WebSocketServerIndexPage;
|
||||
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
|
||||
import org.jboss.netty.handler.codec.http.HttpRequest;
|
||||
import org.jboss.netty.handler.codec.http.HttpResponse;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.PingWebSocketFrame;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.PongWebSocketFrame;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
|
||||
import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
|
||||
import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpMethod.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
|
||||
import static org.jboss.netty.handler.codec.http.HttpVersion.*;
|
||||
|
||||
/**
|
||||
* Handles handshakes and messages
|
||||
*/
|
||||
public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler {
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketSslServerHandler.class);
|
||||
|
||||
private static final String WEBSOCKET_PATH = "/websocket";
|
||||
|
||||
private WebSocketServerHandshaker handshaker;
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
Object msg = e.getMessage();
|
||||
if (msg instanceof HttpRequest) {
|
||||
handleHttpRequest(ctx, (HttpRequest) msg);
|
||||
} else if (msg instanceof WebSocketFrame) {
|
||||
handleWebSocketFrame(ctx, (WebSocketFrame) msg);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) throws Exception {
|
||||
// Allow only GET methods.
|
||||
if (req.getMethod() != GET) {
|
||||
sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN));
|
||||
return;
|
||||
}
|
||||
|
||||
// Send the demo page and favicon.ico
|
||||
if ("/".equals(req.getUri())) {
|
||||
HttpResponse res = new DefaultHttpResponse(HTTP_1_1, OK);
|
||||
|
||||
ChannelBuffer content = WebSocketServerIndexPage.getContent(getWebSocketLocation(req));
|
||||
|
||||
res.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8");
|
||||
setContentLength(res, content.readableBytes());
|
||||
|
||||
res.setContent(content);
|
||||
sendHttpResponse(ctx, req, res);
|
||||
return;
|
||||
}
|
||||
|
||||
if ("/favicon.ico".equals(req.getUri())) {
|
||||
HttpResponse res = new DefaultHttpResponse(HTTP_1_1, NOT_FOUND);
|
||||
sendHttpResponse(ctx, req, res);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handshake
|
||||
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
||||
getWebSocketLocation(req), null, false);
|
||||
handshaker = wsFactory.newHandshaker(req);
|
||||
if (handshaker == null) {
|
||||
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());
|
||||
} else {
|
||||
handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
|
||||
|
||||
// Check for closing frame
|
||||
if (frame instanceof CloseWebSocketFrame) {
|
||||
handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);
|
||||
return;
|
||||
}
|
||||
if (frame instanceof PingWebSocketFrame) {
|
||||
ctx.getChannel().write(new PongWebSocketFrame(frame.getBinaryData()));
|
||||
return;
|
||||
}
|
||||
if (!(frame instanceof TextWebSocketFrame)) {
|
||||
throw new UnsupportedOperationException(String.format("%s frame types not supported", frame.getClass()
|
||||
.getName()));
|
||||
}
|
||||
|
||||
// Send the uppercase string back.
|
||||
String request = ((TextWebSocketFrame) frame).getText();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Channel %s received %s", ctx.getChannel().getId(), request));
|
||||
}
|
||||
ctx.getChannel().write(new TextWebSocketFrame(request.toUpperCase()));
|
||||
}
|
||||
|
||||
private static void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
|
||||
// Generate an error page if response status code is not OK (200).
|
||||
if (res.getStatus().getCode() != 200) {
|
||||
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
|
||||
setContentLength(res, res.getContent().readableBytes());
|
||||
}
|
||||
|
||||
// Send the response and close the connection if necessary.
|
||||
ChannelFuture f = ctx.getChannel().write(res);
|
||||
if (!isKeepAlive(req) || res.getStatus().getCode() != 200) {
|
||||
f.addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
||||
private static String getWebSocketLocation(HttpRequest req) {
|
||||
return "wss://" + req.headers().get(HOST) + WEBSOCKET_PATH;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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 org.jboss.netty.example.http.websocketx.sslserver;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
|
||||
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
|
||||
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
|
||||
import org.jboss.netty.handler.ssl.SslHandler;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class WebSocketSslServerPipelineFactory implements ChannelPipelineFactory {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
// Create a default pipeline implementation.
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
SSLEngine engine = WebSocketSslServerSslContext.getInstance().getServerContext().createSSLEngine();
|
||||
engine.setUseClientMode(false);
|
||||
pipeline.addLast("ssl", new SslHandler(engine));
|
||||
|
||||
pipeline.addLast("decoder", new HttpRequestDecoder());
|
||||
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
|
||||
pipeline.addLast("encoder", new HttpResponseEncoder());
|
||||
pipeline.addLast("handler", new WebSocketSslServerHandler());
|
||||
return pipeline;
|
||||
}
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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 org.jboss.netty.example.http.websocketx.sslserver;
|
||||
|
||||
import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.FileInputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.Security;
|
||||
|
||||
/**
|
||||
* Creates a {@link SSLContext} for just server certificates.
|
||||
*/
|
||||
public final class WebSocketSslServerSslContext {
|
||||
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketSslServerSslContext.class);
|
||||
private static final String PROTOCOL = "TLS";
|
||||
|
||||
private final SSLContext _serverContext;
|
||||
|
||||
/**
|
||||
* Returns the singleton instance for this class
|
||||
*/
|
||||
public static WebSocketSslServerSslContext getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* SingletonHolder is loaded on the first execution of Singleton.getInstance() or the first access to
|
||||
* SingletonHolder.INSTANCE, not before.
|
||||
*
|
||||
* See http://en.wikipedia.org/wiki/Singleton_pattern
|
||||
*/
|
||||
private interface SingletonHolder {
|
||||
WebSocketSslServerSslContext INSTANCE = new WebSocketSslServerSslContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for singleton
|
||||
*/
|
||||
private WebSocketSslServerSslContext() {
|
||||
SSLContext serverContext = null;
|
||||
try {
|
||||
// Key store (Server side certificate)
|
||||
String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
|
||||
if (algorithm == null) {
|
||||
algorithm = "SunX509";
|
||||
}
|
||||
|
||||
try {
|
||||
String keyStoreFilePath = System.getProperty("keystore.file.path");
|
||||
String keyStoreFilePassword = System.getProperty("keystore.file.password");
|
||||
|
||||
KeyStore ks = KeyStore.getInstance("JKS");
|
||||
FileInputStream fin = new FileInputStream(keyStoreFilePath);
|
||||
ks.load(fin, keyStoreFilePassword.toCharArray());
|
||||
|
||||
// Set up key manager factory to use our key store
|
||||
// Assume key password is the same as the key store file
|
||||
// password
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
|
||||
kmf.init(ks, keyStoreFilePassword.toCharArray());
|
||||
|
||||
// Initialise the SSLContext to work with our key managers.
|
||||
serverContext = SSLContext.getInstance(PROTOCOL);
|
||||
serverContext.init(kmf.getKeyManagers(), null, null);
|
||||
} catch (Exception e) {
|
||||
throw new Error("Failed to initialize the server-side SSLContext", e);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error("Error initializing SslContextManager. " + ex.getMessage(), ex);
|
||||
}
|
||||
System.exit(1);
|
||||
} finally {
|
||||
_serverContext = serverContext;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the server context with server side key store
|
||||
*/
|
||||
public SSLContext getServerContext() {
|
||||
return _serverContext;
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* <p>This package contains an example web socket web server with server SSL.
|
||||
* <p>To run this example, follow the steps below:
|
||||
* <dl>
|
||||
* <dt>Step 1. Generate Your Key
|
||||
* <dd>
|
||||
* {@code keytool -genkey -keystore mySrvKeystore -keyalg RSA}.
|
||||
* Make sure that you set the key password to be the same the key file password.
|
||||
* <dt>Step 2. Specify your key store file and password as system properties
|
||||
* <dd>
|
||||
* {@code -Dkeystore.file.path=<path to mySrvKeystore> -Dkeystore.file.password=<password>}
|
||||
* <dt>Step 3. Run WebSocketSslServer as a Java application
|
||||
* <dd>
|
||||
* Once started, you can test the web server against your browser by navigating to https://localhost:8081/
|
||||
* </dl>
|
||||
* <p>To find out more about setting up key stores, refer to this
|
||||
* <a href="http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html">giude</a>.
|
||||
*/
|
||||
package org.jboss.netty.example.http.websocketx.sslserver;
|
||||
|
@ -15,10 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.local;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
@ -34,76 +30,69 @@ import org.jboss.netty.handler.codec.string.StringEncoder;
|
||||
import org.jboss.netty.handler.logging.LoggingHandler;
|
||||
import org.jboss.netty.logging.InternalLogLevel;
|
||||
|
||||
public class LocalExample {
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
private final String port;
|
||||
public final class LocalExample {
|
||||
|
||||
public LocalExample(String port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() throws IOException {
|
||||
// Address to bind on / connect to.
|
||||
LocalAddress socketAddress = new LocalAddress(port);
|
||||
|
||||
// Configure the server.
|
||||
ServerBootstrap sb = new ServerBootstrap(
|
||||
new DefaultLocalServerChannelFactory());
|
||||
|
||||
// Set up the default server-side event pipeline.
|
||||
EchoServerHandler handler = new EchoServerHandler();
|
||||
sb.getPipeline().addLast("handler", handler);
|
||||
|
||||
// Start up the server.
|
||||
sb.bind(socketAddress);
|
||||
|
||||
// Configure the client.
|
||||
ClientBootstrap cb = new ClientBootstrap(
|
||||
new DefaultLocalClientChannelFactory());
|
||||
|
||||
// Set up the client-side pipeline factory.
|
||||
cb.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
return Channels.pipeline(
|
||||
new StringDecoder(),
|
||||
new StringEncoder(),
|
||||
new LoggingHandler(InternalLogLevel.INFO));
|
||||
}
|
||||
});
|
||||
|
||||
// Make the connection attempt to the server.
|
||||
ChannelFuture channelFuture = cb.connect(socketAddress);
|
||||
channelFuture.awaitUninterruptibly();
|
||||
|
||||
// Read commands from the stdin.
|
||||
System.out.println("Enter text (quit to end)");
|
||||
ChannelFuture lastWriteFuture = null;
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||
for (; ;) {
|
||||
String line = in.readLine();
|
||||
if (line == null || "quit".equalsIgnoreCase(line)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Sends the received line to the server.
|
||||
lastWriteFuture = channelFuture.getChannel().write(line);
|
||||
}
|
||||
|
||||
// Wait until all messages are flushed before closing the channel.
|
||||
if (lastWriteFuture != null) {
|
||||
lastWriteFuture.awaitUninterruptibly();
|
||||
}
|
||||
channelFuture.getChannel().close();
|
||||
|
||||
// Wait until the connection is closed or the connection attempt fails.
|
||||
channelFuture.getChannel().getCloseFuture().awaitUninterruptibly();
|
||||
|
||||
// Release all resources used by the local transport.
|
||||
cb.releaseExternalResources();
|
||||
sb.releaseExternalResources();
|
||||
}
|
||||
static final String PORT = System.getProperty("port", "test_port");
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new LocalExample("1").run();
|
||||
// Address to bind on / connect to.
|
||||
LocalAddress socketAddress = new LocalAddress(PORT);
|
||||
|
||||
// Create the bootstraps for both client and server side.
|
||||
ServerBootstrap sb = new ServerBootstrap(new DefaultLocalServerChannelFactory());
|
||||
ClientBootstrap cb = new ClientBootstrap(new DefaultLocalClientChannelFactory());
|
||||
|
||||
try {
|
||||
// Set up the default server-side event pipeline.
|
||||
EchoServerHandler handler = new EchoServerHandler();
|
||||
sb.getPipeline().addLast("handler", handler);
|
||||
|
||||
// Start up the server.
|
||||
sb.bind(socketAddress);
|
||||
|
||||
// Set up the client-side pipeline factory.
|
||||
cb.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() {
|
||||
return Channels.pipeline(
|
||||
new StringDecoder(),
|
||||
new StringEncoder(),
|
||||
new LoggingHandler(InternalLogLevel.INFO));
|
||||
}
|
||||
});
|
||||
|
||||
// Make the connection attempt to the server.
|
||||
ChannelFuture channelFuture = cb.connect(socketAddress);
|
||||
channelFuture.sync();
|
||||
|
||||
// Read commands from the stdin.
|
||||
System.err.println("Enter text (quit to end)");
|
||||
ChannelFuture lastWriteFuture = null;
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||
for (;;) {
|
||||
String line = in.readLine();
|
||||
if (line == null || "quit".equalsIgnoreCase(line)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Sends the received line to the server.
|
||||
lastWriteFuture = channelFuture.getChannel().write(line);
|
||||
}
|
||||
|
||||
// Wait until all messages are flushed before closing the channel.
|
||||
if (lastWriteFuture != null) {
|
||||
lastWriteFuture.sync();
|
||||
}
|
||||
channelFuture.getChannel().close();
|
||||
|
||||
// Wait until the connection is closed or the connection attempt fails.
|
||||
channelFuture.getChannel().getCloseFuture().sync();
|
||||
} finally {
|
||||
// Release all resources used by the local transport.
|
||||
cb.releaseExternalResources();
|
||||
sb.releaseExternalResources();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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 org.jboss.netty.example.local;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.Channels;
|
||||
import org.jboss.netty.channel.local.DefaultLocalClientChannelFactory;
|
||||
import org.jboss.netty.channel.local.DefaultLocalServerChannelFactory;
|
||||
import org.jboss.netty.channel.local.LocalAddress;
|
||||
import org.jboss.netty.handler.codec.string.StringDecoder;
|
||||
import org.jboss.netty.handler.codec.string.StringEncoder;
|
||||
import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;
|
||||
import org.jboss.netty.handler.logging.LoggingHandler;
|
||||
import org.jboss.netty.logging.InternalLogLevel;
|
||||
|
||||
public class LocalExampleMultithreaded {
|
||||
|
||||
private final String port;
|
||||
|
||||
public LocalExampleMultithreaded(String port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
LocalAddress socketAddress = new LocalAddress(port);
|
||||
|
||||
OrderedMemoryAwareThreadPoolExecutor eventExecutor =
|
||||
new OrderedMemoryAwareThreadPoolExecutor(
|
||||
5, 1000000, 10000000, 100,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
||||
ServerBootstrap sb = new ServerBootstrap(
|
||||
new DefaultLocalServerChannelFactory());
|
||||
|
||||
sb.setPipelineFactory(new LocalServerPipelineFactory(eventExecutor));
|
||||
sb.bind(socketAddress);
|
||||
|
||||
ClientBootstrap cb = new ClientBootstrap(
|
||||
new DefaultLocalClientChannelFactory());
|
||||
|
||||
cb.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
return Channels.pipeline(
|
||||
new StringDecoder(),
|
||||
new StringEncoder(),
|
||||
new LoggingHandler(InternalLogLevel.INFO));
|
||||
}
|
||||
});
|
||||
|
||||
// Read commands from array
|
||||
String[] commands = { "First", "Second", "Third", "quit" };
|
||||
for (int j = 0; j < 5 ; j++) {
|
||||
System.err.println("Start " + j);
|
||||
ChannelFuture channelFuture = cb.connect(socketAddress);
|
||||
channelFuture.awaitUninterruptibly();
|
||||
if (! channelFuture.isSuccess()) {
|
||||
System.err.println("CANNOT CONNECT");
|
||||
channelFuture.getCause().printStackTrace();
|
||||
break;
|
||||
}
|
||||
ChannelFuture lastWriteFuture = null;
|
||||
for (String line: commands) {
|
||||
// Sends the received line to the server.
|
||||
lastWriteFuture = channelFuture.getChannel().write(line);
|
||||
}
|
||||
|
||||
// Wait until all messages are flushed before closing the channel.
|
||||
if (lastWriteFuture != null) {
|
||||
lastWriteFuture.awaitUninterruptibly();
|
||||
}
|
||||
channelFuture.getChannel().close();
|
||||
// Wait until the connection is closed or the connection attempt fails.
|
||||
channelFuture.getChannel().getCloseFuture().awaitUninterruptibly();
|
||||
System.err.println("End " + j);
|
||||
}
|
||||
|
||||
// Release all resources
|
||||
cb.releaseExternalResources();
|
||||
sb.releaseExternalResources();
|
||||
eventExecutor.shutdownNow();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new LocalExampleMultithreaded("1").run();
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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 org.jboss.netty.example.local;
|
||||
|
||||
import org.jboss.netty.channel.ChannelDownstreamHandler;
|
||||
import org.jboss.netty.channel.ChannelEvent;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.ChannelUpstreamHandler;
|
||||
import org.jboss.netty.channel.Channels;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.handler.codec.string.StringDecoder;
|
||||
import org.jboss.netty.handler.codec.string.StringEncoder;
|
||||
import org.jboss.netty.handler.execution.ExecutionHandler;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
public class LocalServerPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
private final ExecutionHandler executionHandler;
|
||||
|
||||
public LocalServerPipelineFactory(Executor eventExecutor) {
|
||||
executionHandler = new ExecutionHandler(eventExecutor);
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
final ChannelPipeline pipeline = Channels.pipeline();
|
||||
pipeline.addLast("decoder", new StringDecoder());
|
||||
pipeline.addLast("encoder", new StringEncoder());
|
||||
pipeline.addLast("executor", executionHandler);
|
||||
pipeline.addLast("handler", new EchoCloseServerHandler());
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
static class EchoCloseServerHandler implements ChannelUpstreamHandler, ChannelDownstreamHandler {
|
||||
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
|
||||
throws Exception {
|
||||
if (e instanceof MessageEvent) {
|
||||
final MessageEvent evt = (MessageEvent) e;
|
||||
String msg = (String) evt.getMessage();
|
||||
if ("quit".equalsIgnoreCase(msg)) {
|
||||
Channels.close(e.getChannel());
|
||||
return;
|
||||
}
|
||||
}
|
||||
ctx.sendUpstream(e);
|
||||
}
|
||||
|
||||
public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) {
|
||||
if (e instanceof MessageEvent) {
|
||||
final MessageEvent evt = (MessageEvent) e;
|
||||
String msg = (String) evt.getMessage();
|
||||
if ("quit".equalsIgnoreCase(msg)) {
|
||||
Channels.close(e.getChannel());
|
||||
return;
|
||||
}
|
||||
System.err.println("SERVER:" + msg);
|
||||
// Write back
|
||||
Channels.write(e.getChannel(), msg);
|
||||
}
|
||||
ctx.sendDownstream(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -19,108 +19,65 @@ import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Sends a list of continent/city pairs to a {@link LocalTimeServer} to
|
||||
* get the local times of the specified cities.
|
||||
*/
|
||||
public class LocalTimeClient {
|
||||
public final class LocalTimeClient {
|
||||
|
||||
private final String host;
|
||||
private final int port;
|
||||
private final Collection<String> cities;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final String HOST = System.getProperty("host", "127.0.0.1");
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8463"));
|
||||
static final List<String> CITIES = Arrays.asList(System.getProperty(
|
||||
"cities", "Asia/Seoul,Europe/Berlin,America/Los_Angeles").split(","));
|
||||
|
||||
public LocalTimeClient(String host, int port, Collection<String> cities) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.cities = new ArrayList<String>();
|
||||
this.cities.addAll(cities);
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Set up.
|
||||
ClientBootstrap bootstrap = new ClientBootstrap(
|
||||
new NioClientSocketChannelFactory(
|
||||
Executors.newCachedThreadPool(),
|
||||
Executors.newCachedThreadPool()));
|
||||
try {
|
||||
// Configure the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new LocalTimeClientPipelineFactory(sslCtx));
|
||||
|
||||
// Configure the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new LocalTimeClientPipelineFactory());
|
||||
// Make a new connection.
|
||||
ChannelFuture connectFuture = bootstrap.connect(new InetSocketAddress(HOST, PORT));
|
||||
|
||||
// Make a new connection.
|
||||
ChannelFuture connectFuture =
|
||||
bootstrap.connect(new InetSocketAddress(host, port));
|
||||
// Wait until the connection is made successfully.
|
||||
Channel channel = connectFuture.sync().getChannel();
|
||||
|
||||
// Wait until the connection is made successfully.
|
||||
Channel channel = connectFuture.awaitUninterruptibly().getChannel();
|
||||
// Get the handler instance to initiate the request.
|
||||
LocalTimeClientHandler handler = channel.getPipeline().get(LocalTimeClientHandler.class);
|
||||
|
||||
// Get the handler instance to initiate the request.
|
||||
LocalTimeClientHandler handler =
|
||||
channel.getPipeline().get(LocalTimeClientHandler.class);
|
||||
// Request and get the response.
|
||||
List<String> response = handler.getLocalTimes(CITIES);
|
||||
|
||||
// Request and get the response.
|
||||
List<String> response = handler.getLocalTimes(cities);
|
||||
// Close the connection.
|
||||
channel.close().awaitUninterruptibly();
|
||||
// Close the connection.
|
||||
channel.close().sync();
|
||||
|
||||
// Shut down all thread pools to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
|
||||
// Print the response at last but not least.
|
||||
Iterator<String> i1 = cities.iterator();
|
||||
Iterator<String> i2 = response.iterator();
|
||||
while (i1.hasNext()) {
|
||||
System.out.format("%28s: %s%n", i1.next(), i2.next());
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Print usage if necessary.
|
||||
if (args.length < 3) {
|
||||
printUsage();
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse options.
|
||||
String host = args[0];
|
||||
int port = Integer.parseInt(args[1]);
|
||||
Collection<String> cities = parseCities(args, 2);
|
||||
if (cities == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
new LocalTimeClient(host, port, cities).run();
|
||||
}
|
||||
|
||||
private static void printUsage() {
|
||||
System.err.println(
|
||||
"Usage: " + LocalTimeClient.class.getSimpleName() +
|
||||
" <host> <port> <continent/city_name> ...");
|
||||
System.err.println(
|
||||
"Example: " + LocalTimeClient.class.getSimpleName() +
|
||||
" localhost 8080 America/New_York Asia/Seoul");
|
||||
}
|
||||
|
||||
private static final Pattern CITY_PATTERN = Pattern.compile("^[_A-Za-z]+/[_A-Za-z]+$");
|
||||
|
||||
private static List<String> parseCities(String[] args, int offset) {
|
||||
List<String> cities = new ArrayList<String>();
|
||||
for (int i = offset; i < args.length; i ++) {
|
||||
if (!CITY_PATTERN.matcher(args[i]).matches()) {
|
||||
System.err.println("Syntax error: '" + args[i] + '\'');
|
||||
printUsage();
|
||||
return null;
|
||||
// Print the response at last but not least.
|
||||
for (int i = 0; i < CITIES.size(); i ++) {
|
||||
System.out.format("%28s: %s%n", CITIES.get(i), response.get(i));
|
||||
}
|
||||
cities.add(args[i].trim());
|
||||
} finally {
|
||||
// Shut down all thread pools to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
}
|
||||
return cities;
|
||||
}
|
||||
}
|
||||
|
@ -34,15 +34,10 @@ import java.util.Formatter;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class LocalTimeClientHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
LocalTimeClientHandler.class.getName());
|
||||
|
||||
private static final Pattern DELIM = Pattern.compile("/");
|
||||
|
||||
// Stateful properties
|
||||
@ -94,35 +89,27 @@ public class LocalTimeClientHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUpstream(
|
||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
logger.info(e.toString());
|
||||
System.err.println(e);
|
||||
}
|
||||
super.handleUpstream(ctx, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
|
||||
throws Exception {
|
||||
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
channel = e.getChannel();
|
||||
super.channelOpen(ctx, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(
|
||||
ChannelHandlerContext ctx, final MessageEvent e) {
|
||||
boolean offered = answer.offer((LocalTimes) e.getMessage());
|
||||
assert offered;
|
||||
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
|
||||
answer.add((LocalTimes) e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
}
|
||||
|
@ -15,19 +15,29 @@
|
||||
*/
|
||||
package org.jboss.netty.example.localtime;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
public class LocalTimeClientPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
private final SslContext sslCtx;
|
||||
|
||||
public LocalTimeClientPipelineFactory(SslContext sslCtx) {
|
||||
this.sslCtx = sslCtx;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline p = pipeline();
|
||||
if (sslCtx != null) {
|
||||
p.addLast("ssl", sslCtx.newHandler(LocalTimeClient.HOST, LocalTimeClient.PORT));
|
||||
}
|
||||
p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());
|
||||
p.addLast("protobufDecoder", new ProtobufDecoder(LocalTimeProtocol.LocalTimes.getDefaultInstance()));
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -15,25 +15,33 @@
|
||||
*/
|
||||
package org.jboss.netty.example.localtime;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Receives a list of continent/city pairs from a {@link LocalTimeClient} to
|
||||
* get the local times of the specified cities.
|
||||
*/
|
||||
public class LocalTimeServer {
|
||||
public final class LocalTimeServer {
|
||||
|
||||
private final int port;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8463"));
|
||||
|
||||
public LocalTimeServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
||||
new NioServerSocketChannelFactory(
|
||||
@ -41,19 +49,9 @@ public class LocalTimeServer {
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
// Set up the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new LocalTimeServerPipelineFactory());
|
||||
bootstrap.setPipelineFactory(new LocalTimeServerPipelineFactory(sslCtx));
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
new LocalTimeServer(port).run();
|
||||
bootstrap.bind(new InetSocketAddress(PORT));
|
||||
}
|
||||
}
|
||||
|
@ -30,36 +30,28 @@ import org.jboss.netty.example.localtime.LocalTimeProtocol.Locations;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static java.util.Calendar.*;
|
||||
|
||||
public class LocalTimeServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
LocalTimeServerHandler.class.getName());
|
||||
|
||||
@Override
|
||||
public void handleUpstream(
|
||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
logger.info(e.toString());
|
||||
System.err.println(e);
|
||||
}
|
||||
super.handleUpstream(ctx, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(
|
||||
ChannelHandlerContext ctx, MessageEvent e) {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
|
||||
Locations locations = (Locations) e.getMessage();
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
LocalTimes.Builder builder = LocalTimes.newBuilder();
|
||||
for (Location l: locations.getLocationList()) {
|
||||
TimeZone tz = TimeZone.getTimeZone(
|
||||
toString(l.getContinent()) + '/' + l.getCity());
|
||||
TimeZone tz = TimeZone.getTimeZone(toString(l.getContinent()) + '/' + l.getCity());
|
||||
Calendar calendar = getInstance(tz);
|
||||
calendar.setTimeInMillis(currentTime);
|
||||
|
||||
@ -77,12 +69,8 @@ public class LocalTimeServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
||||
|
@ -15,19 +15,29 @@
|
||||
*/
|
||||
package org.jboss.netty.example.localtime;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
public class LocalTimeServerPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
private final SslContext sslCtx;
|
||||
|
||||
public LocalTimeServerPipelineFactory(SslContext sslCtx) {
|
||||
this.sslCtx = sslCtx;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline p = pipeline();
|
||||
if (sslCtx != null) {
|
||||
p.addLast("ssl", sslCtx.newHandler());
|
||||
}
|
||||
p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());
|
||||
p.addLast("protobufDecoder", new ProtobufDecoder(LocalTimeProtocol.Locations.getDefaultInstance()));
|
||||
|
||||
|
@ -15,10 +15,8 @@
|
||||
*/
|
||||
package org.jboss.netty.example.objectecho;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.Channels;
|
||||
@ -27,64 +25,61 @@ import org.jboss.netty.example.echo.EchoClient;
|
||||
import org.jboss.netty.handler.codec.serialization.ClassResolvers;
|
||||
import org.jboss.netty.handler.codec.serialization.ObjectDecoder;
|
||||
import org.jboss.netty.handler.codec.serialization.ObjectEncoder;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Modification of {@link EchoClient} which utilizes Java object serialization.
|
||||
*/
|
||||
public class ObjectEchoClient {
|
||||
public final class ObjectEchoClient {
|
||||
|
||||
private final String host;
|
||||
private final int port;
|
||||
private final int firstMessageSize;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final String HOST = System.getProperty("host", "127.0.0.1");
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
|
||||
static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
|
||||
|
||||
public ObjectEchoClient(String host, int port, int firstMessageSize) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.firstMessageSize = firstMessageSize;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the client.
|
||||
ClientBootstrap bootstrap = new ClientBootstrap(
|
||||
new NioClientSocketChannelFactory(
|
||||
Executors.newCachedThreadPool(),
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
// Set up the pipeline factory.
|
||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
return Channels.pipeline(
|
||||
new ObjectEncoder(),
|
||||
new ObjectDecoder(
|
||||
ClassResolvers.cacheDisabled(getClass().getClassLoader())),
|
||||
new ObjectEchoClientHandler(firstMessageSize));
|
||||
}
|
||||
});
|
||||
try {
|
||||
// Set up the pipeline factory.
|
||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline p = Channels.pipeline(
|
||||
new ObjectEncoder(),
|
||||
new ObjectDecoder(ClassResolvers.cacheDisabled(getClass().getClassLoader())),
|
||||
new ObjectEchoClientHandler(SIZE)
|
||||
);
|
||||
|
||||
// Start the connection attempt.
|
||||
bootstrap.connect(new InetSocketAddress(host, port));
|
||||
}
|
||||
if (sslCtx != null) {
|
||||
p.addFirst("ssl", sslCtx.newHandler(HOST, PORT));
|
||||
}
|
||||
return p;
|
||||
}
|
||||
});
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Print usage if no argument is specified.
|
||||
if (args.length < 2 || args.length > 3) {
|
||||
System.err.println(
|
||||
"Usage: " + ObjectEchoClient.class.getSimpleName() +
|
||||
" <host> <port> [<first message size>]");
|
||||
return;
|
||||
// Start the connection attempt.
|
||||
ChannelFuture f = bootstrap.connect(new InetSocketAddress(HOST, PORT));
|
||||
|
||||
// Wait until the connection attempt is finished and then the connection is closed.
|
||||
f.sync().getChannel().getCloseFuture().sync();
|
||||
} finally {
|
||||
bootstrap.releaseExternalResources();
|
||||
}
|
||||
|
||||
// Parse options.
|
||||
final String host = args[0];
|
||||
final int port = Integer.parseInt(args[1]);
|
||||
final int firstMessageSize;
|
||||
|
||||
if (args.length == 3) {
|
||||
firstMessageSize = Integer.parseInt(args[2]);
|
||||
} else {
|
||||
firstMessageSize = 256;
|
||||
}
|
||||
|
||||
new ObjectEchoClient(host, port, firstMessageSize).run();
|
||||
}
|
||||
}
|
||||
|
@ -15,12 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.objectecho;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jboss.netty.channel.ChannelEvent;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ChannelState;
|
||||
@ -29,6 +23,10 @@ import org.jboss.netty.channel.ExceptionEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* Handler implementation for the object echo client. It initiates the
|
||||
* ping-pong traffic between the object echo client and server by sending the
|
||||
@ -36,9 +34,6 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
*/
|
||||
public class ObjectEchoClientHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
ObjectEchoClientHandler.class.getName());
|
||||
|
||||
private final List<Integer> firstMessage;
|
||||
private final AtomicLong transferredMessages = new AtomicLong();
|
||||
|
||||
@ -47,8 +42,7 @@ public class ObjectEchoClientHandler extends SimpleChannelUpstreamHandler {
|
||||
*/
|
||||
public ObjectEchoClientHandler(int firstMessageSize) {
|
||||
if (firstMessageSize <= 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"firstMessageSize: " + firstMessageSize);
|
||||
throw new IllegalArgumentException("firstMessageSize: " + firstMessageSize);
|
||||
}
|
||||
firstMessage = new ArrayList<Integer>(firstMessageSize);
|
||||
for (int i = 0; i < firstMessageSize; i ++) {
|
||||
@ -61,37 +55,30 @@ public class ObjectEchoClientHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUpstream(
|
||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent &&
|
||||
((ChannelStateEvent) e).getState() != ChannelState.INTEREST_OPS) {
|
||||
logger.info(e.toString());
|
||||
System.err.println(e);
|
||||
}
|
||||
super.handleUpstream(ctx, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelConnected(
|
||||
ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
// Send the first message if this handler is a client-side handler.
|
||||
e.getChannel().write(firstMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(
|
||||
ChannelHandlerContext ctx, MessageEvent e) {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
// Echo back the received object to the server.
|
||||
transferredMessages.incrementAndGet();
|
||||
e.getChannel().write(e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.objectecho;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
@ -27,19 +24,30 @@ import org.jboss.netty.example.echo.EchoServer;
|
||||
import org.jboss.netty.handler.codec.serialization.ClassResolvers;
|
||||
import org.jboss.netty.handler.codec.serialization.ObjectDecoder;
|
||||
import org.jboss.netty.handler.codec.serialization.ObjectEncoder;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Modification of {@link EchoServer} which utilizes Java object serialization.
|
||||
*/
|
||||
public class ObjectEchoServer {
|
||||
public final class ObjectEchoServer {
|
||||
|
||||
private final int port;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
|
||||
|
||||
public ObjectEchoServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
||||
new NioServerSocketChannelFactory(
|
||||
@ -48,26 +56,19 @@ public class ObjectEchoServer {
|
||||
|
||||
// Set up the pipeline factory.
|
||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
return Channels.pipeline(
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline p = Channels.pipeline(
|
||||
new ObjectEncoder(),
|
||||
new ObjectDecoder(
|
||||
ClassResolvers.cacheDisabled(getClass().getClassLoader())),
|
||||
new ObjectDecoder(ClassResolvers.cacheDisabled(getClass().getClassLoader())),
|
||||
new ObjectEchoServerHandler());
|
||||
if (sslCtx != null) {
|
||||
p.addFirst("ssl", sslCtx.newHandler());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
});
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
new ObjectEchoServer(port).run();
|
||||
bootstrap.bind(new InetSocketAddress(PORT));
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.objectecho;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jboss.netty.channel.ChannelEvent;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ChannelState;
|
||||
@ -27,15 +23,14 @@ import org.jboss.netty.channel.ExceptionEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* Handles both client-side and server-side handler depending on which
|
||||
* constructor was called.
|
||||
*/
|
||||
public class ObjectEchoServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
ObjectEchoServerHandler.class.getName());
|
||||
|
||||
private final AtomicLong transferredMessages = new AtomicLong();
|
||||
|
||||
public long getTransferredMessages() {
|
||||
@ -43,30 +38,23 @@ public class ObjectEchoServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUpstream(
|
||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent &&
|
||||
((ChannelStateEvent) e).getState() != ChannelState.INTEREST_OPS) {
|
||||
logger.info(e.toString());
|
||||
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent && ((ChannelStateEvent) e).getState() != ChannelState.INTEREST_OPS) {
|
||||
System.err.println(e);
|
||||
}
|
||||
super.handleUpstream(ctx, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(
|
||||
ChannelHandlerContext ctx, MessageEvent e) {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
// Echo back the received object to the client.
|
||||
transferredMessages.incrementAndGet();
|
||||
e.getChannel().write(e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
}
|
||||
|
@ -33,17 +33,15 @@ import java.util.concurrent.Executors;
|
||||
* Because SSL and GZIP are enabled on demand, 5 combinations per protocol
|
||||
* are possible: none, SSL only, GZIP only, SSL + GZIP, and GZIP + SSL.
|
||||
*/
|
||||
public class PortUnificationServer {
|
||||
public final class PortUnificationServer {
|
||||
|
||||
private final SslContext sslCtx;
|
||||
private final int port;
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8080"));
|
||||
|
||||
public PortUnificationServer(SslContext sslCtx, int port) {
|
||||
this.sslCtx = sslCtx;
|
||||
this.port = port;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL context
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
final SslContext sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
||||
new NioServerSocketChannelFactory(
|
||||
@ -52,28 +50,12 @@ public class PortUnificationServer {
|
||||
|
||||
// Set up the event pipeline factory.
|
||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
public ChannelPipeline getPipeline() {
|
||||
return Channels.pipeline(new PortUnificationServerHandler(sslCtx));
|
||||
}
|
||||
});
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
|
||||
// Configure SSL context
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
final SslContext sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
|
||||
// Start the server.
|
||||
new PortUnificationServer(sslCtx, port).run();
|
||||
bootstrap.bind(new InetSocketAddress(PORT));
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ public class PortUnificationServerHandler extends FrameDecoder {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {
|
||||
// Will use the first 5 bytes to detect a protocol.
|
||||
if (buffer.readableBytes() < 5) {
|
||||
return null;
|
||||
|
@ -15,62 +15,34 @@
|
||||
*/
|
||||
package org.jboss.netty.example.proxy;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
|
||||
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
|
||||
public class HexDumpProxy {
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
private final int localPort;
|
||||
private final String remoteHost;
|
||||
private final int remotePort;
|
||||
public final class HexDumpProxy {
|
||||
|
||||
public HexDumpProxy(int localPort, String remoteHost, int remotePort) {
|
||||
this.localPort = localPort;
|
||||
this.remoteHost = remoteHost;
|
||||
this.remotePort = remotePort;
|
||||
}
|
||||
static final int LOCAL_PORT = Integer.parseInt(System.getProperty("localPort", "8443"));
|
||||
static final String REMOTE_HOST = System.getProperty("remoteHost", "www.google.com");
|
||||
static final int REMOTE_PORT = Integer.parseInt(System.getProperty("remotePort", "443"));
|
||||
|
||||
public void run() {
|
||||
System.err.println(
|
||||
"Proxying *:" + localPort + " to " +
|
||||
remoteHost + ':' + remotePort + " ...");
|
||||
public static void main(String[] args) {
|
||||
System.err.println("Proxying *:" + LOCAL_PORT + " to " + REMOTE_HOST + ':' + REMOTE_PORT + " ...");
|
||||
|
||||
// Configure the bootstrap.
|
||||
Executor executor = Executors.newCachedThreadPool();
|
||||
ServerBootstrap sb = new ServerBootstrap(
|
||||
new NioServerSocketChannelFactory(executor, executor));
|
||||
ServerBootstrap sb = new ServerBootstrap(new NioServerSocketChannelFactory(executor, executor));
|
||||
|
||||
// Set up the event pipeline factory.
|
||||
ClientSocketChannelFactory cf =
|
||||
new NioClientSocketChannelFactory(executor, executor);
|
||||
ClientSocketChannelFactory cf = new NioClientSocketChannelFactory(executor, executor);
|
||||
|
||||
sb.setPipelineFactory(
|
||||
new HexDumpProxyPipelineFactory(cf, remoteHost, remotePort));
|
||||
sb.setPipelineFactory(new HexDumpProxyPipelineFactory(cf));
|
||||
|
||||
// Start up the server.
|
||||
sb.bind(new InetSocketAddress(localPort));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Validate command line options.
|
||||
if (args.length != 3) {
|
||||
System.err.println(
|
||||
"Usage: " + HexDumpProxy.class.getSimpleName() +
|
||||
" <local port> <remote host> <remote port>");
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse command line options.
|
||||
int localPort = Integer.parseInt(args[0]);
|
||||
String remoteHost = args[1];
|
||||
int remotePort = Integer.parseInt(args[2]);
|
||||
|
||||
new HexDumpProxy(localPort, remoteHost, remotePort).run();
|
||||
sb.bind(new InetSocketAddress(LOCAL_PORT));
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.proxy;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
@ -30,11 +28,11 @@ import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private final ClientSocketChannelFactory cf;
|
||||
private final String remoteHost;
|
||||
private final int remotePort;
|
||||
|
||||
// This lock guards against the race condition that overrides the
|
||||
// OP_READ flag incorrectly.
|
||||
@ -43,16 +41,12 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private volatile Channel outboundChannel;
|
||||
|
||||
public HexDumpProxyInboundHandler(
|
||||
ClientSocketChannelFactory cf, String remoteHost, int remotePort) {
|
||||
public HexDumpProxyInboundHandler(ClientSocketChannelFactory cf) {
|
||||
this.cf = cf;
|
||||
this.remoteHost = remoteHost;
|
||||
this.remotePort = remotePort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
|
||||
throws Exception {
|
||||
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
// Suspend incoming traffic until connected to the remote host.
|
||||
final Channel inboundChannel = e.getChannel();
|
||||
inboundChannel.setReadable(false);
|
||||
@ -60,11 +54,11 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
|
||||
// Start the connection attempt.
|
||||
ClientBootstrap cb = new ClientBootstrap(cf);
|
||||
cb.getPipeline().addLast("handler", new OutboundHandler(e.getChannel()));
|
||||
ChannelFuture f = cb.connect(new InetSocketAddress(remoteHost, remotePort));
|
||||
ChannelFuture f = cb.connect(new InetSocketAddress(HexDumpProxy.REMOTE_HOST, HexDumpProxy.REMOTE_PORT));
|
||||
|
||||
outboundChannel = f.getChannel();
|
||||
f.addListener(new ChannelFutureListener() {
|
||||
public void operationComplete(ChannelFuture future) throws Exception {
|
||||
public void operationComplete(ChannelFuture future) {
|
||||
if (future.isSuccess()) {
|
||||
// Connection attempt succeeded:
|
||||
// Begin to accept incoming traffic.
|
||||
@ -78,10 +72,9 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e)
|
||||
throws Exception {
|
||||
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
|
||||
ChannelBuffer msg = (ChannelBuffer) e.getMessage();
|
||||
//System.out.println(">>> " + ChannelBuffers.hexDump(msg));
|
||||
//System.err.println(">>> " + ChannelBuffers.hexDump(msg));
|
||||
synchronized (trafficLock) {
|
||||
outboundChannel.write(msg);
|
||||
// If outboundChannel is saturated, do not read until notified in
|
||||
@ -93,8 +86,7 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInterestChanged(ChannelHandlerContext ctx,
|
||||
ChannelStateEvent e) throws Exception {
|
||||
public void channelInterestChanged(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
// If inboundChannel is not saturated anymore, continue accepting
|
||||
// the incoming traffic from the outboundChannel.
|
||||
synchronized (trafficLock) {
|
||||
@ -107,16 +99,14 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
|
||||
throws Exception {
|
||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
if (outboundChannel != null) {
|
||||
closeOnFlush(outboundChannel);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
||||
throws Exception {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
closeOnFlush(e.getChannel());
|
||||
}
|
||||
@ -130,10 +120,9 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e)
|
||||
throws Exception {
|
||||
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
|
||||
ChannelBuffer msg = (ChannelBuffer) e.getMessage();
|
||||
//System.out.println("<<< " + ChannelBuffers.hexDump(msg));
|
||||
//System.err.println("<<< " + ChannelBuffers.hexDump(msg));
|
||||
synchronized (trafficLock) {
|
||||
inboundChannel.write(msg);
|
||||
// If inboundChannel is saturated, do not read until notified in
|
||||
@ -145,8 +134,7 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInterestChanged(ChannelHandlerContext ctx,
|
||||
ChannelStateEvent e) throws Exception {
|
||||
public void channelInterestChanged(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
// If outboundChannel is not saturated anymore, continue accepting
|
||||
// the incoming traffic from the inboundChannel.
|
||||
synchronized (trafficLock) {
|
||||
@ -157,14 +145,12 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
|
||||
throws Exception {
|
||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
closeOnFlush(inboundChannel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
||||
throws Exception {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
closeOnFlush(e.getChannel());
|
||||
}
|
||||
|
@ -15,28 +15,23 @@
|
||||
*/
|
||||
package org.jboss.netty.example.proxy;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
public class HexDumpProxyPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
private final ClientSocketChannelFactory cf;
|
||||
private final String remoteHost;
|
||||
private final int remotePort;
|
||||
|
||||
public HexDumpProxyPipelineFactory(
|
||||
ClientSocketChannelFactory cf, String remoteHost, int remotePort) {
|
||||
public HexDumpProxyPipelineFactory(ClientSocketChannelFactory cf) {
|
||||
this.cf = cf;
|
||||
this.remoteHost = remoteHost;
|
||||
this.remotePort = remotePort;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline p = pipeline(); // Note the static import.
|
||||
p.addLast("handler", new HexDumpProxyInboundHandler(cf, remoteHost, remotePort));
|
||||
p.addLast("handler", new HexDumpProxyInboundHandler(cf));
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
@ -15,91 +15,76 @@
|
||||
*/
|
||||
package org.jboss.netty.example.qotm;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.Channels;
|
||||
import org.jboss.netty.channel.FixedReceiveBufferSizePredictorFactory;
|
||||
import org.jboss.netty.channel.socket.DatagramChannel;
|
||||
import org.jboss.netty.channel.socket.DatagramChannelFactory;
|
||||
import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
|
||||
import org.jboss.netty.handler.codec.string.StringDecoder;
|
||||
import org.jboss.netty.handler.codec.string.StringEncoder;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* A UDP broadcast client that asks for a quote of the moment (QOTM) to
|
||||
* {@link QuoteOfTheMomentServer}.
|
||||
* A UDP broadcast client that asks for a quote of the moment (QOTM) to {@link QuoteOfTheMomentServer}.
|
||||
*
|
||||
* Inspired by <a href="http://goo.gl/BsXVR">the official Java tutorial</a>.
|
||||
* Inspired by <a href="http://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html">the official
|
||||
* Java tutorial</a>.
|
||||
*/
|
||||
public class QuoteOfTheMomentClient {
|
||||
public final class QuoteOfTheMomentClient {
|
||||
|
||||
private final int port;
|
||||
|
||||
public QuoteOfTheMomentClient(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
DatagramChannelFactory f =
|
||||
new NioDatagramChannelFactory(Executors.newCachedThreadPool());
|
||||
|
||||
ConnectionlessBootstrap b = new ConnectionlessBootstrap(f);
|
||||
|
||||
// Configure the pipeline factory.
|
||||
b.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
return Channels.pipeline(
|
||||
new StringEncoder(CharsetUtil.ISO_8859_1),
|
||||
new StringDecoder(CharsetUtil.ISO_8859_1),
|
||||
new QuoteOfTheMomentClientHandler());
|
||||
}
|
||||
});
|
||||
|
||||
// Enable broadcast
|
||||
b.setOption("broadcast", "true");
|
||||
|
||||
// Allow packets as large as up to 1024 bytes (default is 768).
|
||||
// You could increase or decrease this value to avoid truncated packets
|
||||
// or to improve memory footprint respectively.
|
||||
//
|
||||
// Please also note that a large UDP packet might be truncated or
|
||||
// dropped by your router no matter how you configured this option.
|
||||
// In UDP, a packet is truncated or dropped if it is larger than a
|
||||
// certain size, depending on router configuration. IPv4 routers
|
||||
// truncate and IPv6 routers drop a large packet. That's why it is
|
||||
// safe to send small packets in UDP.
|
||||
b.setOption(
|
||||
"receiveBufferSizePredictorFactory",
|
||||
new FixedReceiveBufferSizePredictorFactory(1024));
|
||||
|
||||
DatagramChannel c = (DatagramChannel) b.bind(new InetSocketAddress(0));
|
||||
|
||||
// Broadcast the QOTM request to port 8080.
|
||||
c.write("QOTM?", new InetSocketAddress("255.255.255.255", port));
|
||||
|
||||
// QuoteOfTheMomentClientHandler will close the DatagramChannel when a
|
||||
// response is received. If the channel is not closed within 5 seconds,
|
||||
// print an error message and quit.
|
||||
if (!c.getCloseFuture().awaitUninterruptibly(5000)) {
|
||||
System.err.println("QOTM request timed out.");
|
||||
c.close().awaitUninterruptibly();
|
||||
}
|
||||
|
||||
f.releaseExternalResources();
|
||||
}
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "7686"));
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
ConnectionlessBootstrap b = new ConnectionlessBootstrap(
|
||||
new NioDatagramChannelFactory(Executors.newCachedThreadPool()));
|
||||
|
||||
try {
|
||||
// Configure the pipeline factory.
|
||||
b.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() {
|
||||
return Channels.pipeline(
|
||||
new StringEncoder(CharsetUtil.ISO_8859_1),
|
||||
new StringDecoder(CharsetUtil.ISO_8859_1),
|
||||
new QuoteOfTheMomentClientHandler());
|
||||
}
|
||||
});
|
||||
|
||||
// Enable broadcast
|
||||
b.setOption("broadcast", "true");
|
||||
|
||||
// Allow packets as large as up to 1024 bytes (default is 768).
|
||||
// You could increase or decrease this value to avoid truncated packets
|
||||
// or to improve memory footprint respectively.
|
||||
//
|
||||
// Please also note that a large UDP packet might be truncated or
|
||||
// dropped by your router no matter how you configured this option.
|
||||
// In UDP, a packet is truncated or dropped if it is larger than a
|
||||
// certain size, depending on router configuration. IPv4 routers
|
||||
// truncate and IPv6 routers drop a large packet. That's why it is
|
||||
// safe to send small packets in UDP.
|
||||
b.setOption(
|
||||
"receiveBufferSizePredictorFactory",
|
||||
new FixedReceiveBufferSizePredictorFactory(1024));
|
||||
|
||||
DatagramChannel c = (DatagramChannel) b.bind(new InetSocketAddress(0));
|
||||
|
||||
// Broadcast the QOTM request to port 8080.
|
||||
c.write("QOTM?", new InetSocketAddress("255.255.255.255", PORT));
|
||||
|
||||
// QuoteOfTheMomentClientHandler will close the DatagramChannel when a
|
||||
// response is received. If the channel is not closed within 5 seconds,
|
||||
// print an error message and quit.
|
||||
if (!c.getCloseFuture().await(5000)) {
|
||||
System.err.println("QOTM request timed out.");
|
||||
c.close().sync();
|
||||
}
|
||||
} finally {
|
||||
b.releaseExternalResources();
|
||||
}
|
||||
new QuoteOfTheMomentClient(port).run();
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,7 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
public class QuoteOfTheMomentClientHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
|
||||
throws Exception {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
String msg = (String) e.getMessage();
|
||||
if (msg.startsWith("QOTM: ")) {
|
||||
System.out.println("Quote of the Moment: " + msg.substring(6));
|
||||
@ -33,8 +32,7 @@ public class QuoteOfTheMomentClientHandler extends SimpleChannelUpstreamHandler
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
||||
throws Exception {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
@ -15,40 +15,34 @@
|
||||
*/
|
||||
package org.jboss.netty.example.qotm;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.Channels;
|
||||
import org.jboss.netty.channel.FixedReceiveBufferSizePredictorFactory;
|
||||
import org.jboss.netty.channel.socket.DatagramChannelFactory;
|
||||
import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
|
||||
import org.jboss.netty.handler.codec.string.StringDecoder;
|
||||
import org.jboss.netty.handler.codec.string.StringEncoder;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
/**
|
||||
* A UDP server that responds to the QOTM (quote of the moment) request to a
|
||||
* {@link QuoteOfTheMomentClient}.
|
||||
* A UDP server that responds to the QOTM (quote of the moment) request to a {@link QuoteOfTheMomentClient}.
|
||||
*
|
||||
* Inspired by <a href="http://goo.gl/BsXVR">the official Java tutorial</a>.
|
||||
* Inspired by <a href="http://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html">the official
|
||||
* Java tutorial</a>.
|
||||
*/
|
||||
public class QuoteOfTheMomentServer {
|
||||
public final class QuoteOfTheMomentServer {
|
||||
|
||||
private final int port;
|
||||
private static final int PORT = Integer.parseInt(System.getProperty("port", "7686"));
|
||||
|
||||
public QuoteOfTheMomentServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
DatagramChannelFactory f = new NioDatagramChannelFactory();
|
||||
ConnectionlessBootstrap b = new ConnectionlessBootstrap(f);
|
||||
public static void main(String[] args) throws Exception {
|
||||
ConnectionlessBootstrap b = new ConnectionlessBootstrap(new NioDatagramChannelFactory());
|
||||
|
||||
// Configure the pipeline factory.
|
||||
b.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
public ChannelPipeline getPipeline() {
|
||||
return Channels.pipeline(
|
||||
new StringEncoder(CharsetUtil.ISO_8859_1),
|
||||
new StringDecoder(CharsetUtil.ISO_8859_1),
|
||||
@ -74,16 +68,6 @@ public class QuoteOfTheMomentServer {
|
||||
new FixedReceiveBufferSizePredictorFactory(1024));
|
||||
|
||||
// Bind to the port and start the service.
|
||||
b.bind(new InetSocketAddress(port));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
new QuoteOfTheMomentServer(port).run();
|
||||
b.bind(new InetSocketAddress(PORT));
|
||||
}
|
||||
}
|
||||
|
@ -15,13 +15,13 @@
|
||||
*/
|
||||
package org.jboss.netty.example.qotm;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ExceptionEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class QuoteOfTheMomentServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Random random = new Random();
|
||||
@ -43,8 +43,7 @@ public class QuoteOfTheMomentServerHandler extends SimpleChannelUpstreamHandler
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
|
||||
throws Exception {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
String msg = (String) e.getMessage();
|
||||
if ("QOTM?".equals(msg)) {
|
||||
e.getChannel().write("QOTM: " + nextQuote(), e.getRemoteAddress());
|
||||
@ -52,8 +51,7 @@ public class QuoteOfTheMomentServerHandler extends SimpleChannelUpstreamHandler
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
||||
throws Exception {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
// We don't close the channel because we can keep serving requests.
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
@ -32,88 +31,63 @@ import java.util.concurrent.Executors;
|
||||
/**
|
||||
* Simple SSL chat client modified from {@link TelnetClient}.
|
||||
*/
|
||||
public class SecureChatClient {
|
||||
public final class SecureChatClient {
|
||||
|
||||
private final SslContext sslCtx;
|
||||
private final String host;
|
||||
private final int port;
|
||||
static final String HOST = System.getProperty("host", "127.0.0.1");
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8992"));
|
||||
|
||||
public SecureChatClient(SslContext sslCtx, String host, int port) {
|
||||
this.sslCtx = sslCtx;
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
|
||||
|
||||
public void run() throws IOException {
|
||||
// Configure the client.
|
||||
ClientBootstrap bootstrap = new ClientBootstrap(
|
||||
new NioClientSocketChannelFactory(
|
||||
Executors.newCachedThreadPool(),
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
// Configure the pipeline factory.
|
||||
bootstrap.setPipelineFactory(new SecureChatClientPipelineFactory(sslCtx));
|
||||
try {
|
||||
// Configure the pipeline factory.
|
||||
bootstrap.setPipelineFactory(new SecureChatClientPipelineFactory(sslCtx));
|
||||
|
||||
// Start the connection attempt.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
|
||||
// Start the connection attempt.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(HOST, PORT));
|
||||
|
||||
// Wait until the connection attempt succeeds or fails.
|
||||
Channel channel = future.awaitUninterruptibly().getChannel();
|
||||
if (!future.isSuccess()) {
|
||||
future.getCause().printStackTrace();
|
||||
// Wait until the connection attempt succeeds or fails.
|
||||
Channel channel = future.sync().getChannel();
|
||||
|
||||
// Read commands from the stdin.
|
||||
ChannelFuture lastWriteFuture = null;
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||
for (;;) {
|
||||
String line = in.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Sends the received line to the server.
|
||||
lastWriteFuture = channel.write(line + "\r\n");
|
||||
|
||||
// If user typed the 'bye' command, wait until the server closes
|
||||
// the connection.
|
||||
if ("bye".equals(line.toLowerCase())) {
|
||||
channel.getCloseFuture().sync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until all messages are flushed before closing the channel.
|
||||
if (lastWriteFuture != null) {
|
||||
lastWriteFuture.sync();
|
||||
}
|
||||
|
||||
// Close the connection. Make sure the close operation ends because
|
||||
// all I/O operations are asynchronous in Netty.
|
||||
channel.close().sync();
|
||||
} finally {
|
||||
// Shut down all thread pools to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
return;
|
||||
}
|
||||
|
||||
// Read commands from the stdin.
|
||||
ChannelFuture lastWriteFuture = null;
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||
for (;;) {
|
||||
String line = in.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Sends the received line to the server.
|
||||
lastWriteFuture = channel.write(line + "\r\n");
|
||||
|
||||
// If user typed the 'bye' command, wait until the server closes
|
||||
// the connection.
|
||||
if ("bye".equals(line.toLowerCase())) {
|
||||
channel.getCloseFuture().awaitUninterruptibly();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until all messages are flushed before closing the channel.
|
||||
if (lastWriteFuture != null) {
|
||||
lastWriteFuture.awaitUninterruptibly();
|
||||
}
|
||||
|
||||
// Close the connection. Make sure the close operation ends because
|
||||
// all I/O operations are asynchronous in Netty.
|
||||
channel.close().awaitUninterruptibly();
|
||||
|
||||
// Shut down all thread pools to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Print usage if no argument is specified.
|
||||
if (args.length != 2) {
|
||||
System.err.println(
|
||||
"Usage: " + SecureChatClient.class.getSimpleName() +
|
||||
" <host> <port>");
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse options.
|
||||
String host = args[0];
|
||||
int port = Integer.parseInt(args[1]);
|
||||
|
||||
// Configure the SSL context.
|
||||
SslContext sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
|
||||
|
||||
new SecureChatClient(sslCtx, host, port).run();
|
||||
}
|
||||
}
|
||||
|
@ -15,58 +15,34 @@
|
||||
*/
|
||||
package org.jboss.netty.example.securechat;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jboss.netty.channel.ChannelEvent;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ChannelStateEvent;
|
||||
import org.jboss.netty.channel.ExceptionEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
import org.jboss.netty.handler.ssl.SslHandler;
|
||||
|
||||
/**
|
||||
* Handles a client-side channel.
|
||||
*/
|
||||
public class SecureChatClientHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
SecureChatClientHandler.class.getName());
|
||||
|
||||
@Override
|
||||
public void handleUpstream(
|
||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
logger.info(e.toString());
|
||||
System.err.println(e);
|
||||
}
|
||||
super.handleUpstream(ctx, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelConnected(
|
||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
// Get the SslHandler from the pipeline
|
||||
// which were added in SecureChatPipelineFactory.
|
||||
SslHandler sslHandler = ctx.getPipeline().get(SslHandler.class);
|
||||
|
||||
// Begin handshake.
|
||||
sslHandler.handshake();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(
|
||||
ChannelHandlerContext ctx, MessageEvent e) {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public class SecureChatClientPipelineFactory implements ChannelPipelineFactory {
|
||||
this.sslCtx = sslCtx;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
// Add SSL handler first to encrypt and decrypt everything.
|
||||
@ -44,11 +44,10 @@ public class SecureChatClientPipelineFactory implements ChannelPipelineFactory {
|
||||
// and accept any invalid certificates in the client side.
|
||||
// You will need something more complicated to identify both
|
||||
// and server in the real world.
|
||||
pipeline.addLast("ssl", sslCtx.newHandler());
|
||||
pipeline.addLast("ssl", sslCtx.newHandler(SecureChatClient.HOST, SecureChatClient.PORT));
|
||||
|
||||
// On top of the SSL handler, add the text line codec.
|
||||
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
|
||||
8192, Delimiters.lineDelimiter()));
|
||||
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
|
||||
pipeline.addLast("decoder", new StringDecoder());
|
||||
pipeline.addLast("encoder", new StringEncoder());
|
||||
|
||||
|
@ -27,17 +27,14 @@ import java.util.concurrent.Executors;
|
||||
/**
|
||||
* Simple SSL chat server modified from {@link TelnetServer}.
|
||||
*/
|
||||
public class SecureChatServer {
|
||||
public final class SecureChatServer {
|
||||
|
||||
private final SslContext sslCtx;
|
||||
private final int port;
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8992"));
|
||||
|
||||
public SecureChatServer(SslContext sslCtx, int port) {
|
||||
this.sslCtx = sslCtx;
|
||||
this.port = port;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
SslContext sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
||||
new NioServerSocketChannelFactory(
|
||||
@ -48,19 +45,6 @@ public class SecureChatServer {
|
||||
bootstrap.setPipelineFactory(new SecureChatServerPipelineFactory(sslCtx));
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8443;
|
||||
}
|
||||
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
SslContext sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
new SecureChatServer(sslCtx, port).run();
|
||||
bootstrap.bind(new InetSocketAddress(PORT));
|
||||
}
|
||||
}
|
||||
|
@ -29,32 +29,24 @@ import org.jboss.netty.channel.group.DefaultChannelGroup;
|
||||
import org.jboss.netty.handler.ssl.SslHandler;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Handles a server-side channel.
|
||||
*/
|
||||
public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
SecureChatServerHandler.class.getName());
|
||||
|
||||
static final ChannelGroup channels = new DefaultChannelGroup();
|
||||
|
||||
@Override
|
||||
public void handleUpstream(
|
||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
logger.info(e.toString());
|
||||
System.err.println(e);
|
||||
}
|
||||
super.handleUpstream(ctx, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelConnected(
|
||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
|
||||
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
// Get the SslHandler in the current pipeline.
|
||||
// We added it in SecureChatPipelineFactory.
|
||||
final SslHandler sslHandler = ctx.getPipeline().get(SslHandler.class);
|
||||
@ -65,16 +57,14 @@ public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelDisconnected(
|
||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
// Unregister the channel from the global channel list
|
||||
// so the channel does not receive messages anymore.
|
||||
channels.remove(e.getChannel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(
|
||||
ChannelHandlerContext ctx, MessageEvent e) {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
|
||||
// Convert to a String first.
|
||||
String request = (String) e.getMessage();
|
||||
@ -96,12 +86,8 @@ public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
||||
@ -117,11 +103,9 @@ public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
|
||||
if (future.isSuccess()) {
|
||||
// Once session is secured, send a greeting.
|
||||
future.getChannel().write(
|
||||
"Welcome to " + InetAddress.getLocalHost().getHostName() +
|
||||
" secure chat service!\n");
|
||||
"Welcome to " + InetAddress.getLocalHost().getHostName() + " secure chat service!\n");
|
||||
future.getChannel().write(
|
||||
"Your session is protected by " +
|
||||
sslHandler.getEngine().getSession().getCipherSuite() +
|
||||
"Your session is protected by " + sslHandler.getEngine().getSession().getCipherSuite() +
|
||||
" cipher suite.\n");
|
||||
|
||||
// Register the channel to the global channel list
|
||||
|
@ -36,7 +36,7 @@ public class SecureChatServerPipelineFactory implements ChannelPipelineFactory {
|
||||
this.sslCtx = sslCtx;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
public ChannelPipeline getPipeline() {
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
// Add SSL handler first to encrypt and decrypt everything.
|
||||
@ -47,8 +47,7 @@ public class SecureChatServerPipelineFactory implements ChannelPipelineFactory {
|
||||
pipeline.addLast("ssl", sslCtx.newHandler());
|
||||
|
||||
// On top of the SSL handler, add the text line codec.
|
||||
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
|
||||
8192, Delimiters.lineDelimiter()));
|
||||
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
|
||||
pipeline.addLast("decoder", new StringDecoder());
|
||||
pipeline.addLast("encoder", new StringEncoder());
|
||||
|
||||
|
@ -15,97 +15,83 @@
|
||||
*/
|
||||
package org.jboss.netty.example.telnet;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Simplistic telnet client.
|
||||
*/
|
||||
public class TelnetClient {
|
||||
public final class TelnetClient {
|
||||
|
||||
private final String host;
|
||||
private final int port;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final String HOST = System.getProperty("host", "127.0.0.1");
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8992" : "8023"));
|
||||
|
||||
public TelnetClient(String host, int port) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() throws IOException {
|
||||
// Configure the client.
|
||||
ClientBootstrap bootstrap = new ClientBootstrap(
|
||||
new NioClientSocketChannelFactory(
|
||||
Executors.newCachedThreadPool(),
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
// Configure the pipeline factory.
|
||||
bootstrap.setPipelineFactory(new TelnetClientPipelineFactory());
|
||||
try {
|
||||
// Configure the pipeline factory.
|
||||
bootstrap.setPipelineFactory(new TelnetClientPipelineFactory(sslCtx));
|
||||
|
||||
// Start the connection attempt.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
|
||||
// Start the connection attempt.
|
||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(HOST, PORT));
|
||||
|
||||
// Wait until the connection attempt succeeds or fails.
|
||||
Channel channel = future.awaitUninterruptibly().getChannel();
|
||||
if (!future.isSuccess()) {
|
||||
future.getCause().printStackTrace();
|
||||
// Wait until the connection attempt succeeds or fails.
|
||||
Channel channel = future.sync().getChannel();
|
||||
|
||||
// Read commands from the stdin.
|
||||
ChannelFuture lastWriteFuture = null;
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||
for (;;) {
|
||||
String line = in.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Sends the received line to the server.
|
||||
lastWriteFuture = channel.write(line + "\r\n");
|
||||
|
||||
// If user typed the 'bye' command, wait until the server closes
|
||||
// the connection.
|
||||
if ("bye".equals(line.toLowerCase())) {
|
||||
channel.getCloseFuture().sync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until all messages are flushed before closing the channel.
|
||||
if (lastWriteFuture != null) {
|
||||
lastWriteFuture.sync();
|
||||
}
|
||||
|
||||
// Close the connection. Make sure the close operation ends because
|
||||
// all I/O operations are asynchronous in Netty.
|
||||
channel.close().sync();
|
||||
} finally {
|
||||
// Shut down all thread pools to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
return;
|
||||
}
|
||||
|
||||
// Read commands from the stdin.
|
||||
ChannelFuture lastWriteFuture = null;
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||
for (;;) {
|
||||
String line = in.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Sends the received line to the server.
|
||||
lastWriteFuture = channel.write(line + "\r\n");
|
||||
|
||||
// If user typed the 'bye' command, wait until the server closes
|
||||
// the connection.
|
||||
if ("bye".equals(line.toLowerCase())) {
|
||||
channel.getCloseFuture().awaitUninterruptibly();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until all messages are flushed before closing the channel.
|
||||
if (lastWriteFuture != null) {
|
||||
lastWriteFuture.awaitUninterruptibly();
|
||||
}
|
||||
|
||||
// Close the connection. Make sure the close operation ends because
|
||||
// all I/O operations are asynchronous in Netty.
|
||||
channel.close().awaitUninterruptibly();
|
||||
|
||||
// Shut down all thread pools to exit.
|
||||
bootstrap.releaseExternalResources();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Print usage if no argument is specified.
|
||||
if (args.length != 2) {
|
||||
System.err.println(
|
||||
"Usage: " + TelnetClient.class.getSimpleName() +
|
||||
" <host> <port>");
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse options.
|
||||
String host = args[0];
|
||||
int port = Integer.parseInt(args[1]);
|
||||
|
||||
new TelnetClient(host, port).run();
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.telnet;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jboss.netty.channel.ChannelEvent;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ChannelStateEvent;
|
||||
@ -30,32 +27,23 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
*/
|
||||
public class TelnetClientHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
TelnetClientHandler.class.getName());
|
||||
|
||||
@Override
|
||||
public void handleUpstream(
|
||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
logger.info(e.toString());
|
||||
System.err.println(e);
|
||||
}
|
||||
super.handleUpstream(ctx, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(
|
||||
ChannelHandlerContext ctx, MessageEvent e) {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
// Print out the line received from the server.
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
}
|
||||
|
@ -15,25 +15,35 @@
|
||||
*/
|
||||
package org.jboss.netty.example.telnet;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
|
||||
import org.jboss.netty.handler.codec.frame.Delimiters;
|
||||
import org.jboss.netty.handler.codec.string.StringDecoder;
|
||||
import org.jboss.netty.handler.codec.string.StringEncoder;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
/**
|
||||
* Creates a newly configured {@link ChannelPipeline} for a new channel.
|
||||
*/
|
||||
public class TelnetClientPipelineFactory implements
|
||||
ChannelPipelineFactory {
|
||||
public class TelnetClientPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
private final SslContext sslCtx;
|
||||
|
||||
public TelnetClientPipelineFactory(SslContext sslCtx) {
|
||||
this.sslCtx = sslCtx;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() {
|
||||
// Create a default pipeline implementation.
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
if (sslCtx != null) {
|
||||
pipeline.addLast("ssl", sslCtx.newHandler());
|
||||
}
|
||||
|
||||
// Add the text line codec combination first,
|
||||
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
|
||||
8192, Delimiters.lineDelimiter()));
|
||||
|
@ -15,24 +15,32 @@
|
||||
*/
|
||||
package org.jboss.netty.example.telnet;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Simplistic telnet server.
|
||||
*/
|
||||
public class TelnetServer {
|
||||
public final class TelnetServer {
|
||||
|
||||
private final int port;
|
||||
static final boolean SSL = System.getProperty("ssl") != null;
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8992" : "8023"));
|
||||
|
||||
public TelnetServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Configure SSL.
|
||||
final SslContext sslCtx;
|
||||
if (SSL) {
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
|
||||
} else {
|
||||
sslCtx = null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Configure the server.
|
||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
||||
new NioServerSocketChannelFactory(
|
||||
@ -40,19 +48,9 @@ public class TelnetServer {
|
||||
Executors.newCachedThreadPool()));
|
||||
|
||||
// Configure the pipeline factory.
|
||||
bootstrap.setPipelineFactory(new TelnetServerPipelineFactory());
|
||||
bootstrap.setPipelineFactory(new TelnetServerPipelineFactory(sslCtx));
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
bootstrap.bind(new InetSocketAddress(port));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
} else {
|
||||
port = 8080;
|
||||
}
|
||||
new TelnetServer(port).run();
|
||||
bootstrap.bind(new InetSocketAddress(PORT));
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.telnet;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Date;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jboss.netty.channel.ChannelEvent;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.ChannelFutureListener;
|
||||
@ -29,35 +24,31 @@ import org.jboss.netty.channel.ExceptionEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Handles a server-side channel.
|
||||
*/
|
||||
public class TelnetServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
TelnetServerHandler.class.getName());
|
||||
|
||||
@Override
|
||||
public void handleUpstream(
|
||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
||||
if (e instanceof ChannelStateEvent) {
|
||||
logger.info(e.toString());
|
||||
System.err.println(e);
|
||||
}
|
||||
super.handleUpstream(ctx, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelConnected(
|
||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
// Send greeting for a new connection.
|
||||
e.getChannel().write(
|
||||
"Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
|
||||
e.getChannel().write("Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
|
||||
e.getChannel().write("It is " + new Date() + " now.\r\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(
|
||||
ChannelHandlerContext ctx, MessageEvent e) {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
|
||||
// Cast to a String first.
|
||||
// We know it is a String because we put some codec in TelnetPipelineFactory.
|
||||
@ -87,12 +78,8 @@ public class TelnetServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(
|
||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
logger.log(
|
||||
Level.WARNING,
|
||||
"Unexpected exception from downstream.",
|
||||
e.getCause());
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
e.getCause().printStackTrace();
|
||||
e.getChannel().close();
|
||||
}
|
||||
}
|
||||
|
@ -15,25 +15,35 @@
|
||||
*/
|
||||
package org.jboss.netty.example.telnet;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
|
||||
import org.jboss.netty.handler.codec.frame.Delimiters;
|
||||
import org.jboss.netty.handler.codec.string.StringDecoder;
|
||||
import org.jboss.netty.handler.codec.string.StringEncoder;
|
||||
import org.jboss.netty.handler.ssl.SslContext;
|
||||
|
||||
import static org.jboss.netty.channel.Channels.*;
|
||||
|
||||
/**
|
||||
* Creates a newly configured {@link ChannelPipeline} for a new channel.
|
||||
*/
|
||||
public class TelnetServerPipelineFactory implements
|
||||
ChannelPipelineFactory {
|
||||
public class TelnetServerPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
private final SslContext sslCtx;
|
||||
|
||||
public TelnetServerPipelineFactory(SslContext sslCtx) {
|
||||
this.sslCtx = sslCtx;
|
||||
}
|
||||
|
||||
public ChannelPipeline getPipeline() {
|
||||
// Create a default pipeline implementation.
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
if (sslCtx != null) {
|
||||
pipeline.addLast("ssl", sslCtx.newHandler());
|
||||
}
|
||||
|
||||
// Add the text line codec combination first,
|
||||
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
|
||||
8192, Delimiters.lineDelimiter()));
|
||||
|
@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.uptime;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.channel.ChannelHandler;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
@ -28,29 +25,25 @@ import org.jboss.netty.handler.timeout.ReadTimeoutHandler;
|
||||
import org.jboss.netty.util.HashedWheelTimer;
|
||||
import org.jboss.netty.util.Timer;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
|
||||
/**
|
||||
* Connects to a server periodically to measure and print the uptime of the
|
||||
* server. This example demonstrates how to implement reliable reconnection
|
||||
* mechanism in Netty.
|
||||
*/
|
||||
public class UptimeClient {
|
||||
public final class UptimeClient {
|
||||
|
||||
static final String HOST = System.getProperty("host", "127.0.0.1");
|
||||
static final int PORT = Integer.parseInt(System.getProperty("port", "8080"));
|
||||
// Sleep 5 seconds before a reconnection attempt.
|
||||
static final int RECONNECT_DELAY = 5;
|
||||
|
||||
static final int RECONNECT_DELAY = Integer.parseInt(System.getProperty("reconnectDelay", "5"));
|
||||
// Reconnect when the server sends nothing for 10 seconds.
|
||||
private static final int READ_TIMEOUT = 10;
|
||||
static final int READ_TIMEOUT = Integer.parseInt(System.getProperty("readTimeout", "10"));
|
||||
|
||||
private final String host;
|
||||
private final int port;
|
||||
|
||||
public UptimeClient(String host, int port) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Initialize the timer that schedules subsequent reconnection attempts.
|
||||
final Timer timer = new HashedWheelTimer();
|
||||
|
||||
@ -63,38 +56,18 @@ public class UptimeClient {
|
||||
// Configure the pipeline factory.
|
||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
|
||||
private final ChannelHandler timeoutHandler =
|
||||
new ReadTimeoutHandler(timer, READ_TIMEOUT);
|
||||
private final ChannelHandler uptimeHandler =
|
||||
new UptimeClientHandler(bootstrap, timer);
|
||||
private final ChannelHandler timeoutHandler = new ReadTimeoutHandler(timer, READ_TIMEOUT);
|
||||
private final ChannelHandler uptimeHandler = new UptimeClientHandler(bootstrap, timer);
|
||||
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
return Channels.pipeline(
|
||||
timeoutHandler, uptimeHandler);
|
||||
public ChannelPipeline getPipeline() {
|
||||
return Channels.pipeline(timeoutHandler, uptimeHandler);
|
||||
}
|
||||
});
|
||||
|
||||
bootstrap.setOption(
|
||||
"remoteAddress", new InetSocketAddress(host, port));
|
||||
bootstrap.setOption("remoteAddress", new InetSocketAddress(HOST, PORT));
|
||||
|
||||
// Initiate the first connection attempt - the rest is handled by
|
||||
// UptimeClientHandler.
|
||||
bootstrap.connect();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Print usage if no argument is specified.
|
||||
if (args.length != 2) {
|
||||
System.err.println(
|
||||
"Usage: " + UptimeClient.class.getSimpleName() +
|
||||
" <host> <port>");
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse options.
|
||||
String host = args[0];
|
||||
int port = Integer.parseInt(args[1]);
|
||||
|
||||
new UptimeClient(host, port).run();
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,6 @@
|
||||
*/
|
||||
package org.jboss.netty.example.uptime;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ChannelStateEvent;
|
||||
@ -29,6 +25,10 @@ import org.jboss.netty.util.Timeout;
|
||||
import org.jboss.netty.util.Timer;
|
||||
import org.jboss.netty.util.TimerTask;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Keep reconnecting to the server while printing out the current uptime and
|
||||
* connection attempt status.
|
||||
@ -57,7 +57,7 @@ public class UptimeClientHandler extends SimpleChannelUpstreamHandler {
|
||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
println("Sleeping for: " + UptimeClient.RECONNECT_DELAY + 's');
|
||||
timer.newTimeout(new TimerTask() {
|
||||
public void run(Timeout timeout) throws Exception {
|
||||
public void run(Timeout timeout) {
|
||||
println("Reconnecting to: " + getRemoteAddress());
|
||||
bootstrap.connect();
|
||||
}
|
||||
@ -89,7 +89,7 @@ public class UptimeClientHandler extends SimpleChannelUpstreamHandler {
|
||||
ctx.getChannel().close();
|
||||
}
|
||||
|
||||
void println(String msg) {
|
||||
private void println(String msg) {
|
||||
if (startTime < 0) {
|
||||
System.err.format("[SERVER IS DOWN] %s%n", msg);
|
||||
} else {
|
||||
|
@ -1,4 +0,0 @@
|
||||
textarea {
|
||||
width: 500px;
|
||||
height: 300px;
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
(function() {
|
||||
var Sock = function() {
|
||||
var socket;
|
||||
if (!window.WebSocket) {
|
||||
window.WebSocket = window.MozWebSocket;
|
||||
}
|
||||
|
||||
if (window.WebSocket) {
|
||||
socket = new WebSocket("ws://localhost:8080/websocket");
|
||||
socket.onopen = onopen;
|
||||
socket.onmessage = onmessage;
|
||||
socket.onclose = onclose;
|
||||
} else {
|
||||
alert("Your browser does not support Web Socket.");
|
||||
}
|
||||
|
||||
function onopen(event) {
|
||||
getTextAreaElement().value = "Web Socket opened!";
|
||||
}
|
||||
|
||||
function onmessage(event) {
|
||||
appendTextArea(event.data);
|
||||
}
|
||||
|
||||
function onclose(event) {
|
||||
appendTextArea("Web Socket closed");
|
||||
}
|
||||
|
||||
function appendTextArea(newData) {
|
||||
var el = getTextAreaElement();
|
||||
el.value = el.value + '\n' + newData;
|
||||
}
|
||||
|
||||
function getTextAreaElement() {
|
||||
return document.getElementById('responseText');
|
||||
}
|
||||
|
||||
function send(event) {
|
||||
event.preventDefault();
|
||||
if (window.WebSocket) {
|
||||
if (socket.readyState == WebSocket.OPEN) {
|
||||
socket.send(event.target.message.value);
|
||||
} else {
|
||||
alert("The socket is not open.");
|
||||
}
|
||||
}
|
||||
}
|
||||
document.forms.inputform.addEventListener('submit', send, false);
|
||||
}
|
||||
window.addEventListener('load', function() {
|
||||
new Sock();
|
||||
}, false);
|
||||
})();
|
@ -1,18 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Web Socket Example</title>
|
||||
<link rel="stylesheet" href="css/socket.css">
|
||||
<script src="js/socket.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Enter a message</h1>
|
||||
<form name="inputform">
|
||||
<input type="text" name="message" id="message" placeholder="Enter text to be sent" autofocus>
|
||||
<input type="submit" value="Send Web Socket Data">
|
||||
</form>
|
||||
<h2>Repsonse from Server</h2>
|
||||
<textarea id="responseText"></textarea>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user