PNet is an easy to use network library for Java 1.6 or higher.
- Guaranteed data transfer using TCP
- Safe transfer using TLS
- Support for GZIP compression
- Asynchronous
- Completely thread safe
- Optimized, see benchmarks
- Universal logging using SLF4J
- None
PNet can be downloaded from the Maven Central Repository. PNet is released under the MIT license.
- Packets
- Building Packets
- Reading Packets
- Creating a Server
- Creating a Client
- Extra Client functionality
- Using TLS
- Using compression
- Smarter Packet handling
- Multithreading Note
All data is sent using a Packet
. These Packets are immutable and contain the following fields:
- PacketType (Request or Reply)
- Packet ID
- Data
PacketType and Packet ID can be used to identify incoming Packets. Normally, you should not be creating Packets yourself.
To create a Packet, use a PacketBuilder
. This helper object contains several methods to allow easy creation of Packets.
Packet packet = new PacketBuilder(Packet.PacketType.Request)
.withInt(99)
.withString("abc")
.withBoolean(true)
.build();
Just like the PacketBuilder
, there is a PacketReader
.
PacketReader packetReader = new PacketReader(packet);
int i = packetReader.readInt();
The data of the Packet must be read in the same order as it was written!
There are 2 different Server implementations available: PlainServer
and TLSServer
.
Server server = new PlainServer();
Server server = new TLSServer(keyStoreStream, keyStorePassword, keyStoreType);
To use a Server, you might want to add a PNetListener
to catch events.
server.setListener(new PNetListener()
{
@Override
public void onConnect(final Client c)
{
// Hello client!
}
@Override
public void onDisconnect(final Client c)
{
// Goodbye :(
}
@Override
public void onReceive(final Packet p, final Client c) throws IOException
{
// Handle Packet here
}
});
The Server can be started: server.start(port)
and stopped server.stop()
.
There are 2 different Client implementations available: PlainClient
and TLSClient
.
Client client = new PlainClient();
Client client = new TLSClient(trustStoreStream, trustStorePassword, trustStoreType);
A client fires events just like a Server does.
client.setClientListener(new PNetListener()
{
@Override
public void onConnect(final Client c)
{
// Hello server!
}
@Override
public void onDisconnect(final Client c)
{
// Farewell
}
@Override
public void onReceive(final Packet p, final Client c) throws IOException
{
// Handle Packet?
}
});
Use connect(host, port)
to connect, and client.close()
to disconnect.
PNet contains 2 classes which can simplify using Clients even more.
- AsyncClient
- AutoClient
Any Client implementation can be passed to add functionality to.
The AsyncClient
adds asynchronous functionality to a Client.
AsyncClient asyncClient = new AsyncClient(new PlainClient());
asyncClient.connectAsync("localhost", 8080, new AsyncListener()
{
@Override
public void onCompletion(final boolean success)
{
// Success?
}
});
asyncClient.sendAsync(packet, new AsyncListener()
{
@Override
public void onCompletion(final boolean success)
{
// Success?
}
});
The AutoClient
automatically connects to given host:port so you don't have to check if the Client is connected.
AutoClient autoClient = new AutoClient(new TLSClient(), "localhost", 8080);
These implementations can be stacked.
AsyncClient stackedClient = new AsyncClient(new AutoClient(new TLSClient(), "localhost", 8080));
By stacking these implementations, you now have an asynchronous automatically connecting Client.
Note that order is important.
AutoClient invalid = new AutoClient(new AsyncClient(new TLSClient()), "localhost", 8080);
In this example, the AutoClient
will call the default connect
and send
, which will render the AsyncClient
completely useless.
If used correctly, the AsyncClient
will expose connectAsync
and sendAsync
, which will call connect
and sync
from the AutoClient
asynchronously.
When using TLSServer
, a key store is required. When using TLSClient
, a trust store is required.
server = new TLSServer(
keyStoreStream,
keyStorePassword,
keyStoreType
);
client = new TLSClient(
trustStoreStream,
trustStorePassword,
trustStoreType
);
SSL debug output can be turned on by calling TLS.setSSLDebug()
.
To get up and running quickly, I recommend using Portecle.
- Create a new PKCS12 keystore (your keystore)
- Generate a keypair
- Export head certificate
- Create a new PKCS12 keystore (your truststore)
- Import the exported certificate
PNet is configured to use the latest, most secure TLS protocols and cipher suites available.
To compress a Packet, use the PacketCompressor
helper class.
Packet compressed = PacketCompressor.compress(packet);
Packet decompressed = PacketCompressor.decompress(packet);
A common mistake people make is to handle all different Packets in the main onReceive
event handler. When handling various Packets with various Packet IDs, make sure to use a PacketDistributer
. A pNetListener
implementation is available to link your distributer to your Client or Server.
PacketDistributer packetDistributer = new PacketDistributer();
client.setClientListener(new DistributerListener(packetDistributer));
server.setListener(new DistributerListener(packetDistributer));
For each Packet ID you want to handle, add a PacketHandler
implementation.
short someID = 666;
packetDistributer.addHandler(someID, new PacketHandler()
{
@Override
public void handlePacket(final Packet p, final Client c) throws IOException
{
// Handle this evil Packet for me please
}
});
Even better: separate all the handlers into their own class.
short anotherID = 123;
packetDistributer.addHandler(anotherID, new anotherHandlerClass());
A default handler can be set by using packetDistributer.setDefaultHandler(PacketHandler)
.
PNet uses a threadpool to handle all threading. If your application needs to shut down immediately, this can be done by killing all threads using ThreadManager.shutdown()
.