I am trying to communicate client and server in one project where my client and server both started in main() of my project having two different threads but when client try to call the answer_is function of server side it will show the below exception. When I run the client and server combined in one project I got the error
xception in thread "Thread-2" java.lang.InstantiationError:
org.apache.xmlrpc.XmlRpcRequest
at org.apache.xmlrpc.XmlRpcRequestProcessor.decodeRequest(XmlRpcRequestProcessor.java:82)
at org.apache.xmlrpc.XmlRpcWorker.execute(XmlRpcWorker.java:143)
at org.apache.xmlrpc.XmlRpcServer.execute(XmlRpcServer.java:139)
at org.apache.xmlrpc.XmlRpcServer.execute(XmlRpcServer.java:125)
at org.apache.xmlrpc.WebServer$Connection.run(WebServer.java:761)
at org.apache.xmlrpc.WebServer$Runner.run(WebServer.java:642)
at java.lang.Thread.run(Thread.java:745)
Exception in thread "Thread-3" java.lang.InstantiationError: org.apache.xmlrpc.XmlRpcRequest
at org.apache.xmlrpc.XmlRpcRequestProcessor.decodeRequest(XmlRpcRequestProcessor.java:82)
at org.apache.xmlrpc.XmlRpcWorker.execute(XmlRpcWorker.java:143)
at org.apache.xmlrpc.XmlRpcServer.execute(XmlRpcServer.java:139)
at org.apache.xmlrpc.XmlRpcServer.execute(XmlRpcServer.java:125)
at org.apache.xmlrpc.WebServer$Connection.run(WebServer.java:761)
at org.apache.xmlrpc.WebServer$Runner.run(WebServer.java:642)
at java.lang.Thread.run(Thread.java:745)
JavaClient: org.apache.xmlrpc.XmlRpcException: Failed to create input stream: Unexpected end of file from server
Here is my code for Project 1 having client and server
Main Class
package serverclienttest;
/**
*
* #author root
*/
public class ServerclientTest {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
try {
ServerThread serverthread = new ServerThread();
Thread t = new Thread(serverthread);
t.start();
ClientThread clientthread = new ClientThread();
Thread t1 = new Thread(clientthread);
t1.start();
} catch (Exception exception) {
System.err.println("WebClientServer: " + exception);
}
}
}
ClientSide
package serverclienttest;
import java.net.URL;
import java.util.Map;
import java.util.Scanner;
import java.util.Vector;
import java.util.*;
import java.io.*;
import java.net.*;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.apache.xmlrpc.client.XmlRpcClient;
import java.util.*;
import java.io.*;
/**
*
* #author root
*/
public class ClientThread implements Runnable{
public void run()
{
try {
// XmlRpcClient server = new XmlRpcClient("http://localhost/RPC2");
XmlRpcClient client = new XmlRpcClient();
XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
config.setServerURL(new URL("http://localhost:5300/RPC2"));
config.setEnabledForExtensions(true);
//Vector params = new Vector();
/* Hashtable params = new Hashtable();
params.put(1, 1);
params.put(2, 2);*/
Object[] testclass = new Object[]{1,2};
client.setConfig(config);
int result = (Integer) client.execute("sample.sum", testclass);
System.out.print("Client Executed");
int sum = ((Integer) result).intValue();
System.out.println("The sum is: "+ sum);
} catch (Exception exception) {
System.err.println("JavaClient: " + exception);
}
}
}
Server Side
public class ServerThread {
public ServerThread() {
System.out.println("Handler registered as answer_is");
}
public Integer sum(int x, int y){
return new Integer(x+y);
}
public void run()
{
try {
System.out.println("Attempting to start XML-RPC Server...");
WebServer server = new WebServer(5300);
server.addHandler("sample", new ServerThread());
server.start();
System.out.println("Started successfully.");
System.out.println("Accepting requests. (Halt program to stop.)");
}
catch (Exception exception){
System.err.println("JavaServer: " + exception);
}
}
But when i wrote server side in another project and run it , it will work fine so plz tell me why client and server not run in same project
"Unexpected end of file from Server" implies that the server accepted and closed the connection without sending a response. It's possible that the system is too busy to handle the request, or that there's a bug that randomly drops connections.
In your ServerclientTest class, you are invoking:
ServerThread serverthread = new ServerThread();
Thread t = new Thread(serverthread);
without implementing Runnable. Try changing the class signature as below:
public class ServerThread implements Runnable
//Server Side This will work for me
import java.io.FileWriter;
import java.io.IOException;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.server.PropertyHandlerMapping;
import org.apache.xmlrpc.server.XmlRpcServer;
import org.apache.xmlrpc.server.XmlRpcServerConfigImpl;
import org.apache.xmlrpc.webserver.WebServer;
/**
*
* #author root
*/
public class ServerThread implements Runnable {
private static final String fileName = "/tmp/sample.txt";
/** Default port. */
private static final int defaultPort = 7777;
/** Password. */
private static final String password = "2isAnOddPrime";
/** Handler name. */
private static final String handlerName = "sample";
public Integer sum(int x, int y) {
return new Integer(x + y);
}
public ServerThread()
{
}
public ServerThread(int port) throws InterruptedException, XmlRpcException, IOException {
System.out.println("Handler registered as answer_is");
// Thread.sleep(5000);
WebServer webServer = new WebServer(port);
XmlRpcServer xmlRpcServer = webServer.getXmlRpcServer();
PropertyHandlerMapping phm = new PropertyHandlerMapping();
phm.addHandler(handlerName,ServerThread.class);
xmlRpcServer.setHandlerMapping(phm);
XmlRpcServerConfigImpl serverConfig = (XmlRpcServerConfigImpl)xmlRpcServer.getConfig();
serverConfig.setEnabledForExtensions(true);
serverConfig.setContentLengthOptional(false);
webServer.start();
System.out.println("Done.\nListening on port: " + port);
xmlRpcServer.setHandlerMapping(phm);
}
private void writeToFile(long prime)
{
try
{
FileWriter out = new FileWriter(fileName);
out.write(prime + "");
out.close();
}
catch (Exception e)
{
System.err.println("Could not write " + prime + " to file " + fileName + "\nReason: " + e.getMessage());
}
}
public void run() {
try {
int port = 5300;
new ServerThread(port);
} catch (Exception exception) {
System.err.println("JavaServer: " + exception);
}
}
}
Related
I am looking for reference where I can get simple program to send a SNMP trap to Apache Kafka topic using Apache Camel.
Please help me if someone can explain the it using simple java program.
My RouteBuilder configuration
import org.apache.camel.builder.RouteBuilder;
public class SimpleRouteBuilder extends RouteBuilder{
#Override
public void configure() throws Exception {
String topicName = "topic=first_topic";
String kafkaServer = "kafka:localhost:9092";
String zooKeeperHost = "zookeeperHost=localhost&zookeeperPort=2181";
String serializerClass = "serializerClass=kafka.serializer.StringEncoder";
String toKafka = new StringBuilder().append(kafkaServer).append("?").append(topicName).append("&")
.append(zooKeeperHost).append("&").append(serializerClass).toString();
System.out.println(toKafka);
from("snmp:127.0.0.1:161?protocol=udp&type=POLL&oids=1.3.6.1.2.1.1.5.0").split().tokenize("\n").to(toKafka);
}
}
Main Method
import org.apache.camel.CamelContext;
import org.apache.camel.impl.DefaultCamelContext;
import org.snmp4j.Snmp;
public class MainApp {
public static void main(String[] args) {
SimpleRouteBuilder routeBuilder = new SimpleRouteBuilder();
CamelContext ctx = new DefaultCamelContext();
try {
ctx.addRoutes(routeBuilder);
ctx.start();
Thread.sleep(5 * 60 * 1000);
ctx.stop();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
I was in wrong direction. The write direction is as below -
Create a Trap sender program.
Create Trap receiver/listener program.
Inside Trap receiver or listener, receive trap and send it to Apache Kafka topic through Apache camel.
POM.XML
add below dependencies -
camel-core
snmp4j
camel-kafka
Trap Sender Program
package <>;
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.snmp4j.*;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.*;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import java.util.Date;
public class Trapsender {
public static final String community = "public";
public static final String Oid = ".1.3.6.1.2.1.1.8";
public static final String ipAddress = "127.0.0.1";
public static final int port = 162;
public static void main(String[] args) {
Trapsender trapv3 = new Trapsender();
trapv3.sendTrap_Version3();
}
public void sendTrap_Version3() {
try {
// Create Transport Mapping
TransportMapping transport = new DefaultUdpTransportMapping();
transport.listen();
// Create Target
CommunityTarget cTarget = new CommunityTarget();
cTarget.setCommunity(new OctetString(community));
cTarget.setVersion(SnmpConstants.version2c);
cTarget.setAddress(new UdpAddress(ipAddress + "/" + port));
cTarget.setRetries(2);
cTarget.setTimeout(10000);
// Create PDU for V3
PDU pdu = new PDU();
pdu.setType(PDU.TRAP);
// need to specify the system up time
pdu.add(new VariableBinding(SnmpConstants.sysUpTime, new OctetString(new Date().toString())));
pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, new OID(Oid)));
pdu.add(new VariableBinding(new OID(Oid), new OctetString("Major")));
// Send the PDU
Snmp snmp = new Snmp(transport);
System.out.println("Sending V2 Trap... Check Wheather NMS is Listening or not? ");
ResponseEvent send = snmp.send(pdu, cTarget);
snmp.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Receiver Trap with Apache Camel
package <>;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.snmp4j.*;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.security.Priv3DES;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.TcpAddress;
import org.snmp4j.smi.TransportIpAddress;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.transport.AbstractTransportMapping;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;
import java.io.IOException;
public class Trapreceiver implements CommandResponder {
public static CamelContext ctx=null;
public static ProducerTemplate producer=null;
public static void main(String[] args) {
Trapreceiver snmp4jTrapReceiver = new Trapreceiver();
SimpleRouteBuilder routeBuilder = new SimpleRouteBuilder();
ctx = new DefaultCamelContext();
producer = ctx.createProducerTemplate();
try {
ctx.addRoutes(routeBuilder);
ctx.start();
}
catch (Exception e) {
e.printStackTrace();
}
// producer.sendBody("direct:start", snmp);
try {
snmp4jTrapReceiver.listen(new UdpAddress("localhost/162"), producer);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Trap Listner
*/
public synchronized void listen(TransportIpAddress address, ProducerTemplate producer)
throws IOException {
AbstractTransportMapping transport;
if (address instanceof TcpAddress) {
transport = new DefaultTcpTransportMapping((TcpAddress) address);
} else {
transport = new DefaultUdpTransportMapping((UdpAddress) address);
}
ThreadPool threadPool = ThreadPool.create("DispatcherPool", 10);
MessageDispatcher mDispathcher = new MultiThreadedMessageDispatcher(
threadPool, new MessageDispatcherImpl());
// add message processing models
mDispathcher.addMessageProcessingModel(new MPv1());
mDispathcher.addMessageProcessingModel(new MPv2c());
// add all security protocols
SecurityProtocols.getInstance().addDefaultProtocols();
SecurityProtocols.getInstance().addPrivacyProtocol(new Priv3DES());
// Create Target
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString("public"));
Snmp snmp = new Snmp(mDispathcher, transport);
snmp.addCommandResponder(this);
transport.listen();
System.out.println("Listening on " + address);
try {
this.wait();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
/**
* This method will be called whenever a pdu is received on the given port
* specified in the listen() method
*/
public synchronized void processPdu(CommandResponderEvent cmdRespEvent) {
System.out.println("Received PDU...");
PDU pdu = cmdRespEvent.getPDU();
if (pdu != null) {
System.out.println("Trap Type = " + pdu.getType());
System.out.println("Variables = " + pdu.getVariableBindings());
producer.sendBody("direct:start","Variables = " + pdu.getVariableBindings() );
}
}
}
Can someone please resolve this issue.
Using JDK 1.8, I am trying to build a very simple chat application in Java using Sockets. In my client class as soon as following line executes
Message returnMessage = (Message) objectInputStream.readObject();
it throws exception.
Exception in thread "main" java.io.OptionalDataException
I am writing only objects of type Message to the stream and reading objects of type Message, since i wrote once, i dont think i am doing anything wrong in reading them in sequence.
Q. Also please let me know what is the best way to debug this type of application, how to hit the breakpoint in server while running client ?
Client
package com.company;
import sun.misc.SharedSecrets;
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException, ClassNotFoundException{
Socket socket = new Socket("localhost", Server.PORT);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String readerInput = bufferedReader.readLine();
String[] readerInputTokens = readerInput.split("\u0020");
if(readerInputTokens.length != 2) {
System.out.println("Usage: Client <integer> <integer>");
} else {
Integer firstNumber = Integer.decode(readerInputTokens[0]);
Integer secondNumber = Integer.decode(readerInputTokens[1]);
Message message = new Message(firstNumber, secondNumber);
objectOutputStream.writeObject(message);
System.out.println("Reading Object .... ");
Message returnMessage = (Message) objectInputStream.readObject();
System.out.println(returnMessage.getResult());
socket.close();
}
}
public static boolean isInteger(String value) {
boolean returnValue = true;
try{Integer.parseInt(value);}
catch (Exception ex){ returnValue = false; }
return returnValue;
}
}
Server
package com.company;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public final static int PORT = 4446;
public static void main(String[] args) throws IOException, ClassNotFoundException {
new Server().runServer();
}
public void runServer() throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Server up & ready for connections ...");
// This while loop is necessary to make this server able to continuously in listning mode
// So that whenever a client tries to connect, it let it connect.
while (true){
Socket socket = serverSocket.accept(); // Server is ready to accept connectiosn;.
// Initialize Server Thread.
new ServerThread(socket).start();
}
}
}
Sever Thread
package com.company;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class ServerThread extends Thread {
private Socket socket = null;
ServerThread(Socket socket){
this.socket = socket;
}
public void run() {
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeChars("\n");
objectOutputStream.flush();
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Message message = (Message) objectInputStream.readObject();
multiplyNumbers(message);
System.out.println("Writing: "+message.toString());
objectOutputStream.writeObject(message);
System.out.println("Message Written");
socket.close();
} catch( IOException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
private void multiplyNumbers(Message message) {
message.setResult(message.getFirstNumber().intValue() * message.getSecondNumber().intValue());
}
}
Message Class
package com.company;
import java.io.Serializable;
public class Message implements Serializable {
private static final long serialVersionUID = -72233630512719664L;
Integer firstNumber = null;
Integer secondNumber = null;
Integer result = null;
public Message(Integer firstNumber, Integer secondNumber) {
this.firstNumber = firstNumber;
this.secondNumber = secondNumber;
}
public Integer getFirstNumber() {
return this.firstNumber;
}
public Integer getSecondNumber() {
return this.secondNumber;
}
public Integer getResult() {
return this.result;
}
public void setResult(Integer result) {
this.result = result;
}
#Override
public String toString() {
return "Message{" +
"firstNumber=" + firstNumber +
", secondNumber=" + secondNumber +
", result=" + result +
'}';
}
}
objectOutputStream.writeChars("\n");
Why are you writing a newline to an ObjectOutputStream? You're never reading it. Don't do that. Remove this wherever encountered.
I want to create a server that can accept multiple connections and then bind 2 clients as a pair and forward the data between these 2 clients. But it is about multiple pairs of clients. I already have multithread server that can create a new thread for each new connected client. The problem for me is that these threads dont know of each other and somehow I have to connect 2 clients to a connection pair.
For now I just create these pair connection as this: I wait for the first client, then I wait for the second client and then open a thread for the input of client 1 that gets forwarded to client 2 and the other way around. This is not usable for multiple clients.
How can I do this decent?
The way I see it, a client would need to
establish a TCP(?) connection with your server,
identify itself
give the ID of the other client it wishes to talk to
The first that connects would have to be kept on hold (in some global table in your server) until the second client connects.
Once a pair of clients would have been recognized as interlocutors, you would create a pair of threads to forward the data sent by each client to the other one.
UPDATE: Example
ClientSocket.java
package matchmaker;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientSocket implements Closeable {
private final Socket socket;
private final InputStream in;
private final OutputStream out;
private final String ownId;
private final String peerId;
public ClientSocket(Socket socket) throws IOException {
this.socket = socket;
this.in = socket.getInputStream();
this.out = socket.getOutputStream();
DataInputStream din = new DataInputStream(in);
this.ownId = din.readUTF();
this.peerId = din.readUTF();
}
public ClientSocket(String server, int port, String ownId, String peerId)
throws IOException {
this.socket = new Socket(server, port);
this.socket.setTcpNoDelay(true);
this.in = socket.getInputStream();
this.out = socket.getOutputStream();
this.ownId = ownId;
this.peerId = peerId;
DataOutputStream dout = new DataOutputStream(out);
dout.writeUTF(ownId);
dout.writeUTF(peerId);
}
public String getOwnId() {
return ownId;
}
public String getPeerId() {
return peerId;
}
public InputStream getInputStream() {
return in;
}
public OutputStream getOutputStream() {
return out;
}
#Override
public void close() throws IOException {
socket.close();
}
}
Matchmaker.java: the server
package matchmaker;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Matchmaker extends Thread {
private static final Logger LOG
= Logger.getLogger(Matchmaker.class.getName());
private final int port;
private final Map<ClientPair,ClientSocket> waiting = new HashMap<>();
public static void main(String[] args) {
try {
int port = 1234;
int st = 0;
for (String arg: args) {
switch (st) {
case 0:
switch (arg) {
case "-p":
st = 1;
break;
default:
System.out.println("Unknown option: " + arg);
return;
}
break;
case 1:
port = Integer.parseInt(arg);
st = 0;
break;
}
}
Matchmaker server = new Matchmaker(port);
server.start();
server.join();
} catch (InterruptedException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
private Matchmaker(int port) {
this.port = port;
setDaemon(true);
}
#Override
public void run() {
try {
ServerSocket server = new ServerSocket(port);
while (true) {
ClientSocket socket = new ClientSocket(server.accept());
ClientPair pair = new ClientPair(
socket.getOwnId(), socket.getPeerId());
ClientSocket other;
synchronized(this) {
other = waiting.remove(pair.opposite());
if (other == null) {
waiting.put(pair, socket);
}
}
if (other != null) {
LOG.log(Level.INFO, "Establishing connection for {0}",
pair);
establishConnection(socket, other);
} else {
LOG.log(Level.INFO, "Waiting for counterpart {0}", pair);
}
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
private void establishConnection(ClientSocket socket, ClientSocket other)
throws IOException {
Thread thread = new StreamCopier(
socket.getInputStream(), other.getOutputStream());
thread.start();
thread = new StreamCopier(
other.getInputStream(), socket.getOutputStream());
thread.start();
}
}
StreamCopier.java: a thread that reads from an InputStream and writes to an OutputStream
package matchmaker;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class StreamCopier extends Thread {
private static final Logger LOG
= Logger.getLogger(StreamCopier.class.getName());
private final InputStream in;
private final OutputStream out;
public StreamCopier(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
setDaemon(true);
}
#Override
public void run() {
LOG.info("Start stream copier");
try {
for (int b = in.read(); b != -1; b = in.read()) {
out.write(b);
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
} finally {
LOG.info("End stream copier");
try {
out.close();
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
}
ClientPair.java: a pair of client IDs
package matchmaker;
public class ClientPair {
private final String client1;
private final String client2;
public ClientPair(String client1, String client2) {
this.client1 = client1;
this.client2 = client2;
}
public String getClient1() {
return client1;
}
public String getClient2() {
return client2;
}
public ClientPair opposite() {
return new ClientPair(client2, client1);
}
#Override
public int hashCode() {
int hash = 5;
hash = 73 * hash + client1.hashCode();
hash = 73 * hash + client2.hashCode();
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ClientPair other = (ClientPair) obj;
return client1.equals(other.client1) && client2.equals(other.client2);
}
#Override
public String toString() {
return "[" + client1 + "," + client2 + "]";
}
}
ReaderClient.java: a sample client that reads from the socket and writes to standard output
package matchmaker;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ReaderClient {
private static final Logger LOG = Logger.getLogger(ReaderClient.class.getName());
public static void main(String[] args) {
try (ClientSocket client
= new ClientSocket("localhost", 1234, "reader", "writer")) {
Reader reader
= new InputStreamReader(client.getInputStream(), "UTF-8");
BufferedReader in = new BufferedReader(reader);
for (String s = in.readLine(); s != null; s = in.readLine()) {
System.out.println(s);
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
WriterClient.java: a sample client that writes to the socket
package matchmaker;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.logging.Level;
import java.util.logging.Logger;
public class WriterClient {
private static final Logger LOG = Logger.getLogger(ReaderClient.class.getName());
public static void main(String[] args) {
try (ClientSocket client
= new ClientSocket("localhost", 1234, "writer", "reader")) {
Writer writer
= new OutputStreamWriter(client.getOutputStream(), "UTF-8");
PrintWriter out = new PrintWriter(writer);
for (int i = 0; i < 30; ++i) {
out.println("Message line " + i);
}
out.flush();
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
I am using httpcore libraries 4.3.2 to make a custom http server to communicate with some clients (android devices).
The clients manage to communicate (post an xml) with the server but the response of the server is very slow.
My code is based on the ElementalHttpServer of apache samples. Can i find somewhere else better samples for the httpcore libraries?
Also i can not find how to set the parameteres or to finetune the httpserver because the HttParams lib is deprecated.
If i use the com.sun.net.httpserver.HttpServer httpserver my clients are connecting without problem. It is better to stay with suns libs or to use apaches?
Thanks in advance.
This is the code i used:
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.ServerSocket;
import java.net.Socket;
import javax.net.ssl.SSLServerSocketFactory;
import org.apache.http.ConnectionClosedException;
import org.apache.http.HttpConnectionFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpServerConnection;
import org.apache.http.HttpStatus;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.DefaultBHttpServerConnection;
import org.apache.http.impl.DefaultBHttpServerConnectionFactory;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.HttpProcessorBuilder;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.HttpService;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
import org.apache.http.protocol.UriHttpRequestHandlerMapper;
import org.apache.http.util.EntityUtils;
public class Thread_Main_httpcore2 implements Runnable {
public Thread_Main_httpcore2() {
}//Thread_Main()
#Override
public void run() {
int port = 20010;
// Set up the HTTP protocol processor
HttpProcessor httpproc = HttpProcessorBuilder.create()
.add(new ResponseDate())
.add(new ResponseServer("Test/1.1"))
.add(new ResponseContent())
.add(new ResponseConnControl()).build();
// Set up request handlers
UriHttpRequestHandlerMapper reqistry = new UriHttpRequestHandlerMapper();
//// Set up the HTTP service
HttpService httpService = new HttpService(httpproc, reqistry);
reqistry.register("*", new Thread_Main_httpcore2.HttpReqHandler());
SSLServerSocketFactory sf = null;
try {
Thread t = new RequestListenerThread(port, httpService, sf);
t.setDaemon(false);
t.start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
static class HttpReqHandler implements HttpRequestHandler {
public HttpReqHandler() {
super();
}
public void handle(
final HttpRequest request,
final HttpResponse response,
final HttpContext context) throws HttpException, IOException {
String xml_stream="";
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
byte[] entityContent;
if (entity == null) {
entityContent = new byte[0];
} else {
entityContent = EntityUtils.toByteArray(entity);
}
//byte[] entityContent = EntityUtils.toByteArray(entity);
System.out.println("Incoming entity content (bytes): " + entityContent.length);
xml_stream = new String(entityContent);
}
StringBuilder resp_xml = new StringBuilder();
resp_xml.append("Returns an xml to the client");
StringEntity entity;
try {
response.setStatusCode(HttpStatus.SC_OK);
entity = new StringEntity(resp_xml.toString(), ContentType.create("text/html", "UTF-8"));
response.setEntity(entity);
} catch (Exception ex_send_resp) {
System.out.println("HttpFileHandler.ex_send_resp "+ ex_send_resp.toString());
}
}
}
static class RequestListenerThread extends Thread {
private final HttpConnectionFactory<DefaultBHttpServerConnection> connFactory;
private final ServerSocket serversocket;
private final HttpService httpService;
public RequestListenerThread(
final int port,
final HttpService httpService,
final SSLServerSocketFactory sf) throws IOException {
this.connFactory = DefaultBHttpServerConnectionFactory.INSTANCE;
this.serversocket = sf != null ? sf.createServerSocket(port) : new ServerSocket(port);
this.httpService = httpService;
}
#Override
public void run() {
System.out.println("Listening on port " + this.serversocket.getLocalPort());
while (!Thread.interrupted()) {
try {
// Set up HTTP connection
Socket socket = this.serversocket.accept();
System.out.println("Incoming connection from " + socket.getInetAddress());
HttpServerConnection conn = this.connFactory.createConnection(socket);
// Start worker thread
Thread t = new WorkerThread(this.httpService, conn);
t.setDaemon(true);
t.start();
} catch (InterruptedIOException ex) {
break;
} catch (IOException e) {
System.err.println("I/O error initialising connection thread: "
+ e.getMessage());
break;
}
}
}
}
static class WorkerThread extends Thread {
private final HttpService httpservice;
private final HttpServerConnection conn;
public WorkerThread(
final HttpService httpservice,
final HttpServerConnection conn) {
super();
this.httpservice = httpservice;
this.conn = conn;
}
#Override
public void run() {
System.out.println("New connection thread");
HttpContext context = new BasicHttpContext(null);
try {
while (!Thread.interrupted() && this.conn.isOpen()) {
this.httpservice.handleRequest(this.conn, context);
}
} catch (ConnectionClosedException ex) {
System.err.println("Client closed connection");
} catch (IOException ex) {
System.err.println("I/O error: " + ex.getMessage());
} catch (HttpException ex) {
System.err.println("Unrecoverable HTTP protocol violation: " + ex.getMessage());
} finally {
try {
this.conn.shutdown();
} catch (IOException ignore) {
}
}
}
}
}
THE SCENE:
I am writing a echo client and server. The data being transfered is a string:
Client encode a string,and send it to server.
Server recv data, decode string, then encode the received string, send it back to client.
The above process will be repeated 100000 times.(Note: the connection is persistent).
DEFERENT CONTIONS:
When I run ONE server and TWO client at the same time, everything is ok,every client receives 100000 messages and terminated normally.
But When I add a ExecutionHandler on server, and then run ONE server and TWO client at the same time, one client will never terminate, and the network traffic is zero.
I cant locate the key point of this problem for now, will you give me some suggestions?
MY CODE:
string encoder , string decoder, client handler , server handler , client main ,server main.
//Decoder=======================================================
import java.nio.charset.Charset;
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.FrameDecoder;
public class Dcd extends FrameDecoder {
public static final Charset cs = Charset.forName("utf8");
#Override
protected Object decode(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buffer) throws Exception {
if (buffer.readableBytes() < 4) {
return null;
}
int headlen = 4;
int length = buffer.getInt(0);
if (buffer.readableBytes() < length + headlen) {
return null;
}
String ret = buffer.toString(headlen, length, cs);
buffer.skipBytes(length + headlen);
return ret;
}
}
//Encoder =======================================================
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;
public class Ecd extends OneToOneEncoder {
#Override
protected Object encode(ChannelHandlerContext ctx, Channel channel,
Object msg) throws Exception {
if (!(msg instanceof String)) {
return msg;
}
byte[] data = ((String) msg).getBytes();
ChannelBuffer buf = ChannelBuffers.dynamicBuffer(data.length + 4, ctx
.getChannel().getConfig().getBufferFactory());
buf.writeInt(data.length);
buf.writeBytes(data);
return buf;
}
}
//Client handler =======================================================
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
/**
* Handler implementation for the echo client. It initiates the ping-pong
* traffic between the echo client and server by sending the first message to
* the server.
*/
public class EchoClientHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger
.getLogger(EchoClientHandler.class.getName());
private final AtomicLong transferredBytes = new AtomicLong();
private final AtomicInteger counter = new AtomicInteger(0);
private final AtomicLong startTime = new AtomicLong(0);
private String dd;
/**
* Creates a client-side handler.
*/
public EchoClientHandler(String data) {
dd = data;
}
public long getTransferredBytes() {
return transferredBytes.get();
}
#Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
// Send the first message. Server will not send anything here
// because the firstMessage's capacity is 0.
startTime.set(System.currentTimeMillis());
Channels.write(ctx.getChannel(), dd);
}
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Send back the received message to the remote peer.
transferredBytes.addAndGet(((String) e.getMessage()).length());
int i = counter.incrementAndGet();
int N = 100000;
if (i < N) {
e.getChannel().write(e.getMessage());
} else {
ctx.getChannel().close();
System.out.println(N * 1.0
/ (System.currentTimeMillis() - startTime.get()) * 1000);
}
}
#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.getChannel().close();
}
}
//Client main =======================================================
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
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;
/**
* Sends one message when a connection is open and echoes back any received data
* to the server. Simply put, the echo client initiates the ping-pong traffic
* between the echo client and server by sending the first message to the
* server.
*/
public class EchoClient {
private final String host;
private final int port;
public EchoClient(String host, int port) {
this.host = host;
this.port = port;
}
public void run() {
// Configure the client.
final 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 Dcd(), new Ecd(),
new EchoClientHandler("abcdd"));
}
});
bootstrap.setOption("sendBufferSize", 1048576);
bootstrap.setOption("receiveBufferSize", 1048576);
bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("writeBufferLowWaterMark", 32 * 1024);
bootstrap.setOption("writeBufferHighWaterMark", 64 * 1024);
List<ChannelFuture> list = new ArrayList<ChannelFuture>();
for (int i = 0; i < 1; i++) {
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(
host, port));
// Wait until the connection is closed or the connection
// attempt
// fails.
list.add(future);
}
for (ChannelFuture f : list) {
f.getChannel().getCloseFuture().awaitUninterruptibly();
}
// Shut down thread pools to exit.
bootstrap.releaseExternalResources();
}
private static void testOne() {
final String host = "192.168.0.102";
final int port = 8000;
new EchoClient(host, port).run();
}
public static void main(String[] args) throws Exception {
testOne();
}
}
//server handler =======================================================
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
/**
* 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() {
return transferredBytes.get();
}
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Send back the received message to the remote peer.
transferredBytes.addAndGet(((String) e.getMessage()).length());
Channels.write(ctx.getChannel(), e.getMessage());
}
#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.getChannel().close();
}
}
//Server main =======================================================
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.execution.ExecutionHandler;
import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;
/**
* Echoes back any received data from a client.
*/
public class EchoServer {
private final int port;
public EchoServer(int port) {
this.port = port;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
System.out.println(Runtime.getRuntime().availableProcessors() * 2);
final ExecutionHandler executionHandler = new ExecutionHandler(
new OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576));
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
System.out.println("new pipe");
return Channels.pipeline(new Dcd(), new Ecd(),
executionHandler, new EchoServerHandler());
}
});
bootstrap.setOption("child.sendBufferSize", 1048576);
bootstrap.setOption("child.receiveBufferSize", 1048576);
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.writeBufferLowWaterMark", 32 * 1024);
bootstrap.setOption("child.writeBufferHighWaterMark", 64 * 1024);
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port = 8000;
new EchoServer(port).run();
}
}
I have found the reason now, it is a hard work, but full with pleasure.
When added a ExecutionHandler, the message will be wrapped into a Runnable task, and will be executed in a ChildExecutor. The key point is here : A task maybe added to ChildExecutor when the executor almostly exit , then is will be ignored by the ChildExecutor.
I added three lines code and some comments, the final code looks like below, and it works now,should I mail to the author? :
private final class ChildExecutor implements Executor, Runnable {
private final Queue<Runnable> tasks = QueueFactory
.createQueue(Runnable.class);
private final AtomicBoolean isRunning = new AtomicBoolean();
public void execute(Runnable command) {
// TODO: What todo if the add return false ?
tasks.add(command);
if (!isRunning.get()) {
doUnorderedExecute(this);
} else {
}
}
public void run() {
// check if its already running by using CAS. If so just return
// here. So in the worst case the thread
// is executed and do nothing
boolean acquired = false;
if (isRunning.compareAndSet(false, true)) {
acquired = true;
try {
Thread thread = Thread.currentThread();
for (;;) {
final Runnable task = tasks.poll();
// if the task is null we should exit the loop
if (task == null) {
break;
}
boolean ran = false;
beforeExecute(thread, task);
try {
task.run();
ran = true;
onAfterExecute(task, null);
} catch (RuntimeException e) {
if (!ran) {
onAfterExecute(task, e);
}
throw e;
}
}
//TODO NOTE (I added): between here and "isRunning.set(false)",some new tasks maybe added.
} finally {
// set it back to not running
isRunning.set(false);
}
}
//TODO NOTE (I added): Do the remaining works.
if (acquired && !isRunning.get() && tasks.peek() != null) {
doUnorderedExecute(this);
}
}
}
This was a bug and will be fixed in 3.4.0.Alpha2.
See https://github.com/netty/netty/issues/234