I was trying to run a performance test for Kryonet RMI, the test results are not convincing. However I think I may not be doing things in the right way. Can I get some feedback on the code below.
SERVER
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.esotericsoftware.kryonet.Server;
import com.esotericsoftware.kryonet.rmi.ObjectSpace;
public class Razor {
static int port = 2551;
static String send = null;
// Data Creator, creates data of size s.getBytes().length * 10
static String createMsg(String s){
StringBuilder sb = new StringBuilder();
for (int i = 0 ; i < 10; i++){
sb.append(s);
}
System.out.println(sb.toString().getBytes().length);
return sb.toString();
}
// Test Interface
public static interface TestInterface {
public String getName (String name);
}
//Class implementing the test interface.
static private class TestImpl implements TestInterface {
public String getName (String name) {
return send;
}
}
public static void main (String[] args) throws Exception {
// Creating data of size 160 bytes
send = createMsg("FooAndBarAndLazy");
Server server = new Server();
Kryo kryo = server.getKryo();
ObjectSpace.registerClasses(kryo);
kryo.register(TestInterface.class);
server.start();
server.bind(port);
System.out.println("Server started on " + port);
TestImpl test = new TestImpl();
final ObjectSpace objectSpace = new ObjectSpace();
objectSpace.register(123, test);
server.addListener(new Listener() {
public void connected (final Connection connection) {
objectSpace.addConnection(connection);
}
});
}
}
CLIENT
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryonet.Client;
import com.esotericsoftware.kryonet.rmi.ObjectSpace;
public class TBone {
static int port = 2551;
// Bytes to MB converter
public static float b2mb(long bytes){
float bb = bytes;
float ll = 1024 * 1024;
return bb/ll;
}
// Nono Seconds to seconds converter
public static float ns2s(long nsecs){
float f = nsecs;
float t = 1000000000;
return f/t;
}
public static void main (String[] args) throws Exception {
Client client = new Client();
Kryo kryo = client.getKryo();
ObjectSpace.registerClasses(kryo);
kryo.register(Razor.TestInterface.class);
client.start();
client.connect(50000, "localhost", port);
Razor.TestInterface test = ObjectSpace.getRemoteObject(client, 123, Razor.TestInterface.class);
String profile = null;
int bytes = 0;
long stime = System.nanoTime();
for (int i = 0; i < 1000; i++){
profile = test.getName("");
bytes = bytes + profile.getBytes().length;
if (i %100 == 0) System.out.println("Done : " + i);
}
long etime = System.nanoTime();
System.out.println("Total bytes(MB) : " + b2mb(bytes)+" , " + "Total time : " + ns2s((etime-stime))+" seconds");
client.stop();
}
}
RESULT
Done : 0
Done : 100
Done : 200
Done : 300
Done : 400
Done : 500
Done : 600
Done : 700
Done : 800
Done : 900
Total bytes(MB) : 0.15258789 , Total time : 26.139627 seconds
I would imagine way more performance. Is this a valid test?
This isn't a valid test of performance because even in a localhost request you have a strong latency and your test program wait for the server response before sending next request (as a rmi method call is by nature blocking).
Since you do it 900 time, even without any java processing you have to wait :
number_of_request * travel_time(latency) * 2(one travel for the request and one for the response).
So in your case :
900 * 0.03seconds (ping localhost to see your local latency) ~= 27 seconds
Related
I am working in a project with spring-cloud-gateway. I see that the Request Size limitation filter is yet not available. But I need to develop it. Any idea , is it coming ? or should I start my own development.
I Know that it is difficult to get any answer, as except the developers there are a few persons who are working on it.
I have created a filter named RequestSizeGatewayFilterFactory, It is working fine for our application as of now. But not sure this can be a part of the spring-cloud-gateway project.
package com.api.gateway.somename.filter;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* This filter blocks the request, if the request size is more than
* the permissible size.The default request size is 5 MB
*
* #author Arpan
*/
public class RequestSizeGatewayFilterFactory
extends AbstractGatewayFilterFactory<RequestSizeGatewayFilterFactory.RequestSizeConfig> {
private static String PREFIX = "kMGTPE";
private static String ERROR = "Request size is larger than permissible limit." +
"Request size is %s where permissible limit is %s";
public RequestSizeGatewayFilterFactory() {
super(RequestSizeGatewayFilterFactory.RequestSizeConfig.class);
}
#Override
public GatewayFilter apply(RequestSizeGatewayFilterFactory.RequestSizeConfig requestSizeConfig) {
requestSizeConfig.validate();
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String contentLength = request.getHeaders().getFirst("content-length");
if (!StringUtils.isEmpty(contentLength)) {
Long currentRequestSize = Long.valueOf(contentLength);
if (currentRequestSize > requestSizeConfig.getMaxSize()) {
exchange.getResponse().setStatusCode(HttpStatus.PAYLOAD_TOO_LARGE);
exchange.getResponse().getHeaders().add("errorMessage",
getErrorMessage(currentRequestSize, requestSizeConfig.getMaxSize()));
return exchange.getResponse().setComplete();
}
}
return chain.filter(exchange);
};
}
public static class RequestSizeConfig {
// 5 MB is the default request size
private Long maxSize = 5000000L;
public RequestSizeGatewayFilterFactory.RequestSizeConfig setMaxSize(Long maxSize) {
this.maxSize = maxSize;
return this;
}
public Long getMaxSize() {
return maxSize;
}
public void validate() {
Assert.isTrue(this.maxSize != null && this.maxSize > 0,
"maxSize must be greater than 0");
Assert.isInstanceOf(Long.class, maxSize, "maxSize must be a number");
}
}
private static String getErrorMessage(Long currentRequestSize, Long maxSize) {
return String.format(ERROR,
getHumanReadableByteCount(currentRequestSize),
getHumanReadableByteCount(maxSize));
}
private static String getHumanReadableByteCount(long bytes) {
int unit = 1000;
if (bytes < unit) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = Character.toString(PREFIX.charAt(exp - 1));
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
}
}
And the configuration for the filter is:
When it works as a default filter:
spring:
application:
name: somename
cloud:
gateway:
default-filters:
- Hystrix=default
- RequestSize=7000000
When needs to be applied in some API
# ===========================================
- id: request_size_route
uri: ${test.uri}/upload
predicates:
- Path=/upload
filters:
- name: RequestSize
args:
maxSize: 5000000
Also you need to configure the bean in some component scanable class in your project, which is GatewayAutoConfiguration for the spring-cloud-gateway-core project.
#Bean
public RequestSizeGatewayFilterFactory requestSizeGatewayFilterFactory() {
return new RequestSizeGatewayFilterFactory();
}
I must to do chat server for my subject.
Where is my problem ?
I need to write UDP server class which should send and receive messages from users and transfer it to GUI
Second server should have methods for collect public keys of any user, changing owns ect. Additionally he should store this these keys
What do I have?
I have some code from first server, two Threads for sending and receiving messages and some code in client , but it isn't synchronized. And I don't know how to do it
This is some code from client main method: tfServer --> text field for getting this from user
InetAddress ia = InetAddress.getByName(tfServer.getText());
SenderThread sender = new SenderThread(ia,Integer.valueOf(tfPort.getText()));
sender.start();
ReceiverThread receiver = new ReceiverThread(sender.getSocket());
receiver.start();
First server code :
import java.net.* ;
public class Server {
int port;
private final static int PACKETSIZE = 100 ;
private boolean isStopped = false;
public Server(){
}
public Server(int port) {
this.port = port;
}
public void stop() {
this.isStopped = true;
}
public void start() {
try
{
DatagramSocket socket = new DatagramSocket(this.port) ;
System.out.println( "Serwer gotowy..." ) ;
if(!this.isStopped){
for( ;; ){
DatagramPacket packet = new DatagramPacket( new byte[PACKETSIZE], PACKETSIZE ) ;
socket.receive( packet ) ;
System.out.println( packet.getAddress() + " " + packet.getPort() + ": " + new String(packet.getData()) ) ;
socket.send( packet ) ;
}
}
}
catch( Exception e )
{
System.out.println( e ) ;
}
}
}
And class from first server to receive :
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ReceiverThread extends Thread {
private DatagramSocket udpClientSocket;
private boolean stopped = false;
public ReceiverThread(DatagramSocket ds) throws SocketException {
this.udpClientSocket = ds;
}
public void halt() {
this.stopped = true;
}
public void run() {
byte[] receiveData = new byte[1024];
while (true) {
if (stopped)
return;
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
try {
udpClientSocket.receive(receivePacket);
String serverReply = new String(receivePacket.getData(), 0, receivePacket.getLength());
System.out.println("UDPClient: Response from Server: \"" + serverReply + "\"\n");
Thread.yield();
}
catch (IOException ex) {
System.err.println(ex);
}
}
}
}
Second class from first server to send messages :
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ReceiverThread extends Thread {
private DatagramSocket udpClientSocket;
private boolean stopped = false;
public ReceiverThread(DatagramSocket ds) throws SocketException {
this.udpClientSocket = ds;
}
public void halt() {
this.stopped = true;
}
public void run() {
byte[] receiveData = new byte[1024];
while (true) {
if (stopped)
return;
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
try {
udpClientSocket.receive(receivePacket);
String serverReply = new String(receivePacket.getData(), 0, receivePacket.getLength());
System.out.println("UDPClient: Response from Server: \"" + serverReply + "\"\n");
Thread.yield();
}
catch (IOException ex) {
System.err.println(ex);
}
}
}
}
And server PKI :
public class ServerPKI {
}
Whenever I run my Chat Server it works until the client connects and then I get a Null Pointer exception at
connections.add(socket);
which crashes it and then this happens every time I run it.
I know my client side is fine because I watched a tutorial a few months ago on how to do this and that server works with my client without crashing
private static ServerSocket server;
private static Socket socket;
private static Scanner input;
private static PrintWriter output;
private static final int port = 444;
private static String message;
private static ArrayList<Socket> connections;
private static Server serverClass;
public Server() {
message = "";
connections = new ArrayList<Socket>();
serverClass = new Server();
}
public void run() {
try {
try {
input = new Scanner(socket.getInputStream());
output = new PrintWriter(socket.getOutputStream());
while(true) {
checkConnection();
if(!input.hasNext()) {
return;
}
message = input.nextLine();
System.out.println("Client said: " + message);
for(int i = 1; i <= connections.size(); i++) {
Socket tempSock = (Socket) connections.get(i - 1);
output.println(message);
output.flush();
}
}
}
finally {
socket.close();
}
}
catch(Exception e) {
System.out.print(e);
}
}
public void checkConnection() throws IOException {
if(!socket.isConnected()) {
for(int i = 1; i <= connections.size(); i++) {
if(connections.get(i) == socket) {
connections.remove(i);
}
}
for(int i = 1; i <= connections.size(); i++) {
Socket disconnectedUser = (Socket) connections.get(i - 1);
System.out.println(disconnectedUser + " has Disconnected!");
}
}
}
public static void main(String[] args) throws IOException{
try {
server = new ServerSocket(port);
System.out.println("Waiting for Clients... ");
while(true) {
socket = server.accept();
connections.add(socket);
System.out.println("Client connected from: " + socket.getLocalAddress().getHostName());
Thread thread = new Thread(serverClass);
thread.start();
}
}
catch(Exception e) {
e.printStackTrace();
}
}
If you get an NPE at connections.add(socket), it can only be because connections is null. Which it is, because you haven't constructed an instance of Server: instead you are trying to execute all its code from main(). The only place you call new Server() from is inside the constructor for Server, which you have clearly never executed at all, as you would have got a StackOverflowError from the infinite recursion.
This code is a real mess:
fix the infinite recursion
construct an instance of Server in your main() method
make connections non-static
make socket a local variable in the accept loop
fix your loops to iterate from 0 to connections.size()-1
and try again.
I'm using jnetpcap to analyzing packet. I want to get html web page source code.
However, when I use html.page() to get source code I get some messy code which look like binary code. Can anyone help me? How to solve it?
Not a jnetpcap expert, but I have been using this class for a while and it seems to work. It actually gets many HTTP fields, including its payload.
package br.com.mvalle.ids.sniffer;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.jnetpcap.Pcap;
import org.jnetpcap.PcapIf;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.packet.PcapPacketHandler;
import org.jnetpcap.packet.format.FormatUtils;
import org.jnetpcap.protocol.network.Ip4;
import org.jnetpcap.protocol.tcpip.Http;
import org.jnetpcap.protocol.tcpip.Tcp;
public class Sniffer {
private List<PcapIf> alldevs = new ArrayList<PcapIf>(); // Will be filled with NICs
private StringBuilder errbuf = new StringBuilder(); // For any error msgs
private PcapIf selectedDevice;
private Pcap pcap;
private PcapPacketHandler<String> jpacketHandler;
public Sniffer(){
listDevices();
selectedDevice = selectDevice(1);
openDevice(selectedDevice);
packetHandler();
capturePackets();
}
public void listDevices(){
int r = Pcap.findAllDevs(alldevs, errbuf);
if (r == Pcap.NOT_OK || alldevs.isEmpty()) {
System.err.printf("Can't read list of devices, error is %s", errbuf.toString());
return;
}
System.out.println("Network devices found:");
int i = 0;
for (PcapIf device : alldevs) {
String description =
(device.getDescription() != null) ? device.getDescription()
: "No description available";
System.out.printf("#%d: %s [%s]\n", i++, device.getName(), description);
}
}
private PcapIf selectDevice(int deviceId){
PcapIf device = alldevs.get(1); // We know we have atleast 1 device (parameter changed from 0 to 1)
System.out
.printf("\nChoosing '%s' on your behalf:\n",
(device.getDescription() != null) ? device.getDescription()
: device.getName());
return device;
}
private void openDevice (PcapIf device){
int snaplen = 64 * 1024; // Capture all packets, no trucation
int flags = Pcap.MODE_PROMISCUOUS; // capture all packets
int timeout = 10 * 1000; // 10 seconds in millis
pcap =
Pcap.openLive(device.getName(), snaplen, flags, timeout, errbuf);
if (pcap == null) {
System.err.printf("Error while opening device for capture: "
+ errbuf.toString());
return;
}
}
private void packetHandler(){
jpacketHandler = new PcapPacketHandler<String>() {
Http httpheader = new Http();
public void nextPacket(PcapPacket packet, String user) {
if(packet.hasHeader(httpheader)){
System.out.println(httpheader.toString());
if(httpheader.hasPayload()){
System.out.println("HTTP payload: (string length is "
+new String(httpheader.getPayload()).length()+")");
System.out.println(new String(httpheader.getPayload()));
System.out.println("HTTP truncated? "
+httpheader.isPayloadTruncated());
}
//System.out.println(packet.toString());
}}
};
}
private void capturePackets(){
pcap.loop(pcap.LOOP_INFINITE , jpacketHandler, "Received Packet");
pcap.close();
}
}
Hope it helps.
I have celltable and a simplepager. I am making async calls to the server to return data as a list.
AsyncDataProvider<Entry> provider = new AsyncDataProvider<Entry>() {
#Override
protected void onRangeChanged(HasData<Entry> display) {
final int start = display.getVisibleRange().getStart();
int length = display.getVisibleRange().getLength();
AsyncCallback<List<Entry>> callback = new AsyncCallback<List<Entry>>() {
#Override
public void onFailure(Throwable caught) {
Window.alert(caught.getMessage());
}
#Override
public void onSuccess(List<Entry> result) {
updateRowData(start, result);
}
};
// The remote service that should be implemented
rpcService.fetchEntries(start, length, callback);
}
};
On the server side ...
public List<Entry> fetchEntries(int start, int length) {
if (start > ENTRIES.size())
return new ArrayList<Entry>();
int end = start + length > ENTRIES.size() ? ENTRIES.size() : start
+ length;
ArrayList<Entry> sublist = new ArrayList<Entry>(
(List<Entry>) ENTRIES.subList(start, end));
return sublist;
}
The problem is that I don't know the size of the dataset returned by the aync call. So I cannot set the updateRowCount. So now the next button is always active even though the dataset has only 24 fields. Any ideas ?
How about modifying your RPC service to return a flag as well:
class FetchEntriesResult{
private int totalNumberOfEntries;
private List<Entry> entries;
//getters,setters, constructor etc...
}
And your service method becomes something like:
public FetchEntriesResult fetchEntries(int start, int length) {
if (start > ENTRIES.size())
return new ArrayList<Entry>();
int end = start + length > ENTRIES.size() ? ENTRIES.size() : start
+ length;
ArrayList<Entry> sublist = new ArrayList<Entry>(
(List<Entry>) ENTRIES.subList(start, end));
return new FetchEntriesResult(sublist,ENTRIES.size());
}
Now you can use the FetchEntriesResult.getTotalNumberOfEntries() on the client.