- Saved searches
- Use saved searches to filter your results more quickly
- serpient/java_echo_server
- Name already in use
- Sign In Required
- Launching GitHub Desktop
- Launching GitHub Desktop
- Launching Xcode
- Launching Visual Studio Code
- Latest commit
- Git stats
- Files
- README.md
- fzakaria / EchoApplication.java
- yskszk63 / Echo.java
- Saved searches
- Use saved searches to filter your results more quickly
- License
- xehpuk/echo-http-server
- Name already in use
- Sign In Required
- Launching GitHub Desktop
- Launching GitHub Desktop
- Launching Xcode
- Launching Visual Studio Code
- Latest commit
- Git stats
- Files
- README.md
- About
Saved searches
Use saved searches to filter your results more quickly
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
serpient/java_echo_server
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.md
- Echo Server connects to a client
- Once running, anything typed in the client will be sent to Server
- Server will echo back the message to the client
Check if Java is present: java -version
If not present, follow these instructions.
brew install gradle Verify you have it installed with gradle -v
git clone https://github.com/serpient/java_echo_server.git
4. Run Build to see reports
Within project folder, run ./gradlew build to see the status
Option 1: Default port 1234
Run gradle run to start the server
Run gradle run —args=’1111′ . Replace ‘1111’ with your own custom port
6. Use netcat to interact with server
Open another terminal and run nc localhost the_matching_port_number
Testing Multiple Requests
- To test the simultaneous client sessions with a benchmark, start App.main() and then run ab -r -n 5000 -c 1000 http://localhost:1234/ in another terminal.
- To test the simultaneous client sessions in a real life session, start App.main() and then open at least 2 terminals and run nc localhost 1234 . From here, you can type an input, and the session should echo back your input and then close itself.
Benchmark Result of 1500 Simultaneous Requests with Apache AB
fzakaria / EchoApplication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
import io . netty . bootstrap . Bootstrap ; |
import io . netty . bootstrap . ServerBootstrap ; |
import io . netty . buffer . ByteBuf ; |
import io . netty . buffer . Unpooled ; |
import io . netty . channel . Channel ; |
import io . netty . channel . ChannelFuture ; |
import io . netty . channel . ChannelFutureListener ; |
import io . netty . channel . ChannelHandlerContext ; |
import io . netty . channel . ChannelInitializer ; |
import io . netty . channel . EventLoopGroup ; |
import io . netty . channel . SimpleChannelInboundHandler ; |
import io . netty . channel . nio . NioEventLoopGroup ; |
import io . netty . channel . socket . SocketChannel ; |
import io . netty . channel . socket . nio . NioServerSocketChannel ; |
import io . netty . channel . socket . nio . NioSocketChannel ; |
import io . netty . handler . codec . http . DefaultFullHttpRequest ; |
import io . netty . handler . codec . http . DefaultFullHttpResponse ; |
import io . netty . handler . codec . http . FullHttpRequest ; |
import io . netty . handler . codec . http . FullHttpResponse ; |
import io . netty . handler . codec . http . HttpClientCodec ; |
import io . netty . handler . codec . http . HttpMethod ; |
import io . netty . handler . codec . http . HttpObjectAggregator ; |
import io . netty . handler . codec . http . HttpRequest ; |
import io . netty . handler . codec . http . HttpServerCodec ; |
import io . netty . handler . codec . http . HttpVersion ; |
import io . netty . util . CharsetUtil ; |
import io . netty . util . ResourceLeakDetector ; |
import org . slf4j . Logger ; |
import org . slf4j . LoggerFactory ; |
import java . net . InetSocketAddress ; |
import static io . netty . handler . codec . http . HttpResponseStatus . OK ; |
import static io . netty . handler . codec . http . HttpVersion . HTTP_1_1 ; |
/** |
* A simple HTTP ECHO application |
*/ |
public class EchoApplication |
private static final Logger log = LoggerFactory . getLogger ( EchoApplication . class ); |
public ChannelFuture server ( EventLoopGroup workerGroup ) |
ServerBootstrap b = new ServerBootstrap (); |
b . group ( workerGroup ). channel ( NioServerSocketChannel . class ) |
//Setting InetSocketAddress to port 0 will assign one at random |
. localAddress ( new InetSocketAddress ( 0 )) |
. childHandler ( new ChannelInitializer < SocketChannel >() |
@ Override |
protected void initChannel ( SocketChannel ch ) throws Exception |
//HttpServerCodec is a helper ChildHandler that encompasses |
//both HTTP request decoding and HTTP response encoding |
ch . pipeline (). addLast ( new HttpServerCodec ()); |
//HttpObjectAggregator helps collect chunked HttpRequest pieces into |
//a single FullHttpRequest. If you don’t make use of streaming, this is |
//much simpler to work with. |
ch . pipeline (). addLast ( new HttpObjectAggregator ( 1048576 )); |
//Finally add your FullHttpRequest handler. Real examples might replace this |
//with a request router |
ch . pipeline (). addLast ( new SimpleChannelInboundHandler < FullHttpRequest >() |
@ Override |
public void channelReadComplete ( ChannelHandlerContext ctx ) throws Exception |
ctx . flush (); |
//The close is important here in an HTTP request as it sets the Content-Length of a |
//response body back to the client. |
ctx . close (); |
> |
@ Override |
protected void channelRead0 ( ChannelHandlerContext ctx , FullHttpRequest msg ) throws Exception |
DefaultFullHttpResponse response = new DefaultFullHttpResponse ( HTTP_1_1 , OK , msg . content (). copy ()); |
ctx . write ( response ); |
> |
>); |
> |
>); |
// Start the server & bind to a random port. |
return b . bind (); |
> |
public Bootstrap client () |
EventLoopGroup workerGroup = new NioEventLoopGroup (); |
Bootstrap b = new Bootstrap (); |
b . group ( workerGroup ). channel ( NioSocketChannel . class ) |
. handler ( new ChannelInitializer < SocketChannel >() |
@ Override |
protected void initChannel ( SocketChannel ch ) throws Exception |
//HttpClient codec is a helper ChildHandler that encompasses |
//both HTTP response decoding and HTTP request encoding |
ch . pipeline (). addLast ( new HttpClientCodec ()); |
//HttpObjectAggregator helps collect chunked HttpRequest pieces into |
//a single FullHttpRequest. If you don’t make use of streaming, this is |
//much simpler to work with. |
ch . pipeline (). addLast ( new HttpObjectAggregator ( 1048576 )); |
ch . pipeline (). addLast ( new SimpleChannelInboundHandler < FullHttpResponse >() |
@ Override |
protected void channelRead0 ( ChannelHandlerContext ctx , FullHttpResponse msg ) throws Exception |
final String echo = msg . content (). toString ( CharsetUtil . UTF_8 ); |
log . info ( «Response: <>» , echo ); |
> |
>); |
> |
>); |
return b ; |
> |
public static void main ( String [] args ) throws Exception |
//I find while learning Netty to keep resource leak detecting at Paranoid, |
//however *DO NOT* ship with this level. |
ResourceLeakDetector . setLevel ( ResourceLeakDetector . Level . PARANOID ); |
EventLoopGroup serverWorkgroup = new NioEventLoopGroup (); |
EventLoopGroup clientWorkgroup = new NioEventLoopGroup (); |
EchoApplication app = new EchoApplication (); |
try |
Channel serverChannel = app . server ( serverWorkgroup ). sync (). channel (); |
int PORT = (( InetSocketAddress ) serverChannel . localAddress ()). getPort (); |
System . err . println ( «Open your web browser and navigate to » + |
«://127.0.0.1:» + PORT + ‘/’ ); |
System . err . println ( «Echo back any TEXT with POST HTTP requests» ); |
Bootstrap clientBootstrap = app . client (); |
final ByteBuf content = Unpooled . copiedBuffer ( «Hello World!» , CharsetUtil . UTF_8 ); |
clientBootstrap |
. connect ( serverChannel . localAddress ()) |
. addListener ( new ChannelFutureListener () |
@ Override |
public void operationComplete ( ChannelFuture future ) throws Exception |
// Prepare the HTTP request. |
HttpRequest request = new DefaultFullHttpRequest ( |
HttpVersion . HTTP_1_1 , HttpMethod . POST , «/» , content ); |
// If we don’t set a content length from the client, HTTP RFC |
// dictates that the body must be be empty then and Netty won’t read it. |
request . headers (). set ( «Content-Length» , content . readableBytes ()); |
future . channel (). writeAndFlush ( request ); |
> |
>); |
serverChannel . closeFuture (). sync (); |
> finally |
//Gracefully shutdown both event loop groups |
serverWorkgroup . shutdownGracefully (); |
clientWorkgroup . shutdownGracefully (); |
> |
> |
> |
yskszk63 / Echo.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
import java . io . IOException ; |
import java . net . InetSocketAddress ; |
import java . nio . ByteBuffer ; |
import java . nio . channels . Channels ; |
import com . sun . net . httpserver . HttpExchange ; |
import com . sun . net . httpserver . HttpHandler ; |
import com . sun . net . httpserver . HttpServer ; |
public class Echo implements HttpHandler |
public static void main ( String . args ) throws IOException |
var port = 8080 ; |
var httpd = HttpServer . create ( new InetSocketAddress ( port ), 0 ); |
httpd . createContext ( «/» , new Echo ()); |
httpd . start (); |
> |
public void handle ( HttpExchange exchange ) throws IOException |
exchange . sendResponseHeaders ( 200 , 0 ); |
var buf = ByteBuffer . allocate ( 1024 * 8 ); |
var ingress = Channels . newChannel ( exchange . getRequestBody ()); |
var egress = Channels . newChannel ( exchange . getResponseBody ()); |
try ( ingress ; egress ) |
while ( ingress . read ( buf ) != — 1 ) |
buf . flip (); |
while ( buf . hasRemaining ()) |
egress . write ( buf ); |
> |
buf . clear (); |
> |
> |
> |
> |
Saved searches
Use saved searches to filter your results more quickly
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
HTTP server in plain Java to echo incoming requests.
License
xehpuk/echo-http-server
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.md
This HTTP server does the following:
- Echoes the request headers, potentially prefixed and suffixed.
- Responds to the request, depending on the method:
- PATCH , POST , PUT : Pipes the request body to the response body.
- DELETE , HEAD , GET : Empty 200 OK
- OPTIONS : Behaves like a normal server by returning the allowed headers.
- else: 405 Method Not Allowed
Usage: echo-http-server [-?BHvVw] [-b=] [-h=] [-p=] [-P=] [-s=] -?, --help display this help message -b, --backlog= the maximum number of queued incoming connections to allow (default 1) -B, --body log incoming requests' body -h, --host= the host to listen on (default "localhost") -H, --headers log incoming requests' headers -p, --port= the port to listen on (default 8080) -P, --prefix= the prefix to use for the echoed headers (default "X-Echo-") -s, --suffix= the suffix to use for the echoed headers -v, --verbose log incoming requests completely -V, --version display version info -w, --wait wait for the request to finish before sending the response (some clients may choke otherwise)
About
HTTP server in plain Java to echo incoming requests.