Getting time from public time server using TimeTCPClient - java

I try to use the following code to obtain time from public time server.
package aaa;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.net.TimeTCPClient;
public final class Main
{
public static java.util.Date getNTPDate() {
List<String> hosts = Arrays.asList("0.pool.ntp.org");
for (String host : hosts) {
TimeTCPClient client = new TimeTCPClient();
// We want to timeout if a response takes longer than 5 seconds
client.setDefaultTimeout(5000);
try {
client.connect(host);
java.util.Date ntpDate = client.getDate();
client.disconnect();
// Just to be extra caution.
if (ntpDate != null) {
return ntpDate;
}
}
catch (java.net.SocketException exp) {
exp.printStackTrace();
}
catch (java.io.IOException exp) {
exp.printStackTrace();
}
}
return null;
}
public static final void main(String[] args)
{
System.out.println(getNTPDate());
}
}
However, all the time, I am getting java.net.ConnectException: Connection timed out: connect
I had tried to google for several different time server. However, non of them work. I was wondering, is the problem lies on my code, or the server I choose?

NTP is a different protocol than the time protocol. NTP servers only talk over port UDP/123. Time servers use TCP/37 (which TimeTCPClient appears to implement correctly).
If you want to get a remote time, use an appropriate server (ntp.xs4all.nl appears to be listening on the time port).

You can use the correct approach:
import java.io.IOException;
import java.net.InetAddress;
import java.util.Date;
import org.apache.commons.net.ntp.NTPUDPClient;
import org.apache.commons.net.ntp.TimeInfo;
public final class PublicServerTime {
public static Date getNTPDate() {
String[] hosts = new String[]{
"ntp02.oal.ul.pt", "ntp04.oal.ul.pt",
"ntp.xs4all.nl"};
NTPUDPClient client = new NTPUDPClient();
// We want to timeout if a response takes longer than 5 seconds
client.setDefaultTimeout(5000);
for (String host : hosts) {
try {
InetAddress hostAddr = InetAddress.getByName(host);
System.out.println("> " + hostAddr.getHostName() + "/" + hostAddr.getHostAddress());
TimeInfo info = client.getTime(hostAddr);
Date date = new Date(info.getReturnTime());
return date;
}
catch (IOException e) {
e.printStackTrace();
}
}
client.close();
return null;
}
public static final void main(String[] args) {
System.out.println(getNTPDate());
}

Source:
public class NTPService {
private final static Logger logger = Logger.getLogger(NTPService.class);
private final static int TIMEOUT = 5000;
private final static List<String> hostList =
Arrays.asList("time.windows.com", "nl.pool.ntp.org");
private final NTPUDPClient client = new NTPUDPClient();
public NTPService() {
client.setDefaultTimeout(TIMEOUT);
}
public LocalDateTime getNTPDateTime() {
for (final String host : hostList) {
final LocalDateTime localDateTime = getNTPDateTime(host);
if (null != localDateTime) {
return localDateTime;
}
}
return null;
}
private LocalDateTime getNTPDateTime(final String host) {
try {
client.open();
return convertToLocalDateTime(
TimeStamp.getNtpTime(client.getTime(InetAddress.getByName(host))
.getReturnTime()).getTime());
} catch (final Exception exp) {
logger.warn(String.format("%s: failed to update NTP", host), exp);
return null;
} finally {
if (client.isOpen()) {
client.close();
}
}
}
private LocalDateTime convertToLocalDateTime(final long value) {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(value),
ZoneId.systemDefault());
}
}
Usage:
System.out.println(DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss").
format(new NTPService().getNTPDateTime()));

Related

Java Heap Size monitor solution

I would like to monitor the used java heap size of a jboss service running on windows during serveral days. I first try to use perfmon from windows but I didn't get the value I expected. I can hook jvisualvm to this this service using jmx (server:port), I can also use jconsole or jmc (java mission control). Indeed I cannot use flight recording due to the jvm version.
With jcmd or jstat, I cannot see the process I'm interested in. As I'm new in Java, could someone suggest an application or script which would allow me to catpure those value and push them to a text file for example. I could code something in .Net as well if a library would exist.
Thanks
Below java code records the Java Heap usage (2 mins once by default) to a text file. You can change the code as per your needs. Change the private String jmxUrl = ... as per your environment.
package com.heap.monitor;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.management.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.management.*;
import javax.management.remote.*;
public class HeapMonitor extends Thread {
private JMXServiceURL jmxService = null;
private JMXConnector jmxConnector = null;
protected MBeanServerConnection beanServerConn = null;
private long frequency = 2 * 60 * 1000L; // 2 mins only collects Heap metrics
private String jmxUrl = "service:jmx:rmi:///jndi/rmi://192.168.8.252:12222/jmxrmi";
private String userName = "none";
private String passWord = "none";
public static void main(String[] args) throws InterruptedException {
HeapMonitor heapMonitor = new HeapMonitor();
heapMonitor.join();
}
public HeapMonitor() {
this.start();
}
public void run() {
boolean flag = true;
while(flag) {
try {
beanServerConn = connectToJVM(jmxUrl, userName, passWord);
if(beanServerConn!=null) {
MemoryMXBean mxbean = (MemoryMXBean) ManagementFactory.newPlatformMXBeanProxy(beanServerConn, ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);
try
{
MemoryUsage heapUsage = mxbean.getHeapMemoryUsage();
long used = heapUsage.getUsed();
long max = heapUsage.getMax();
long commited = heapUsage.getCommitted();
long init = heapUsage.getInit();
StringBuffer buffer = new StringBuffer();
Date date = new Date();
buffer.append(date).append(" - ");
buffer.append(init).append(" ").append(commited).append(" ").append(max).append(" ").append(used);
//System.out.println(buffer.toString());
appendStrToFile("heap.txt" , buffer.toString());
}
catch(Exception ee) {
ee.printStackTrace();
}
}
}
catch(Exception e) {
e.printStackTrace();
}
try {
Thread.sleep(frequency);
}
catch(Exception e) {
e.printStackTrace();
}
}
}
protected MBeanServerConnection connectToJVM(String jvmURL, String user, String pass)
{
beanServerConn = null ;
try
{
jmxService = new JMXServiceURL(jvmURL);
Map environment = new HashMap();
int jmxconnect_timeout = 30000;
environment.put("jmx.remote.x.request.waiting.timeout", Long.toString(jmxconnect_timeout));
if(user.equalsIgnoreCase("none")|| (pass.equalsIgnoreCase("none"))){
try{
jmxConnector = JMXConnectorFactory.connect(jmxService,environment);
beanServerConn = jmxConnector.getMBeanServerConnection();
}
catch(IOException ioe){
}
}
else
{
String [] credentials={user,pass};
environment.put(JMXConnector.CREDENTIALS, credentials);
try{
jmxConnector = JMXConnectorFactory.connect(jmxService,environment);
beanServerConn = jmxConnector.getMBeanServerConnection();
}
catch(IOException ioe){
}
}
beanServerConn = jmxConnector.getMBeanServerConnection();
if(beanServerConn == null)
{
System.out.println("Connection to JVM is not established for jvmURL : " + jvmURL);
closeJVMConn();
}
}
catch(Exception ex)
{
System.out.println("Connection to JVM is not established for jvmURL : " + jvmURL);
closeJVMConn();
}
return beanServerConn;
}
public void closeJVMConn(){
try{
beanServerConn = null;
if(jmxConnector != null)
jmxConnector.close();
}
catch(Exception ex){
return;
}
}
public void appendStrToFile(String fileName, String str) {
try {
// Open given file in append mode.
BufferedWriter out = new BufferedWriter(new FileWriter(fileName, true));
out.write(str);
out.newLine();
out.close();
}
catch (IOException e) {
System.out.println("exception occoured" + e);
}
}
}
Using Jconsole, you can view and capture the Heap/Non-Heap Memory usage (also CPU, Threads, etc). In the Jconsole a small popup windows appears when Right Click Heap Memory Usage Graph as shown in the screenshot. You can save the data in the .csv format for the selected time range.

Handler.postDelayed never gets triggered (Java - Android)

I have been trying to find for some time why my Handler does not trigger the events at all but I had no luck in finding it. I will post the entire class and hopefully someone notices a stupid mistake or something.
The class is only managing the lifespan of some sockets (I am doing that because the android devices seem to be very moody when it comes to reopening ports shortly after closing them). The class is a singleton as I want to have awareness of what ports I use everywhere.
package com.ltd.jeefo.alex.routeassistant.wifi.sync.utils;
import android.annotation.SuppressLint;
import android.os.Handler;
import android.support.annotation.Nullable;
import com.ltd.jeefo.alex.routeassistant.logging.ILog;
import com.ltd.jeefo.alex.routeassistant.logging.ScopedLogger;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.HashMap;
/**
* Created by Alex on 16/02/18.
*/
public class SocketsManager {
private static final SocketsManager ourInstance = new SocketsManager();
private static final Handler handler = new Handler();
public static SocketsManager getInstance() {
return ourInstance;
}
#SuppressLint("UseSparseArrays")
private static final HashMap<Integer, ManagedServerSocket> serverSockets = new HashMap<>();
private SocketsManager() {
}
/**
* Method used for obtaining the server socket for a given port
* #param port the port where we want the socket to be opened
* #return the server socket to be used or null if we couldn't start a server socket at that port
*/
public ManagedServerSocket getSocketAtPort(final int port) {
ManagedServerSocket managedServerSocket;
if (serverSockets.containsKey(port)) {
managedServerSocket = serverSockets.get(port);
} else {
managedServerSocket = new ManagedServerSocket(port, handler);
serverSockets.put(port, managedServerSocket);
}
return managedServerSocket;
}
/**
* Closes all the sockets after some delay
*
* #param msDelay the delay in milliseconds
*/
public void closeAllSocketsAfterDelay(final long msDelay) {
for (final ManagedServerSocket managedSocket : serverSockets.values()) {
managedSocket.RequestSocketClosingAfterDelay(msDelay);
}
}
enum ServerSocketStatus {
OPEN_NOT_REQUESTED,
OPEN_FAILED,
OPENED, // there is always a close request started by default, just in case
USER_CLOSE_REQUESTED,
CLOSED
}
public class ManagedServerSocket {
private final ILog logger;
private final static long DEFAULT_CLOSING_TIME_MILLS = 3600000; // one hour
private final static long DEFAULT_RETRY_TIME_MILLS = 15000; // 15 seconds
private final Handler mHandler;
private final int mPort;
private ServerSocket mSocket;
private SocketsManager.ServerSocketStatus serverSocketStatus;
private Long closingTime;
private Runnable defaultClosingRunnable;
private Runnable explicitClosingRunnable;
private ManagedServerSocket(final int port, final Handler handler) {
this.mPort = port;
this.mHandler = handler;
logger = new ScopedLogger(null, ManagedServerSocket.class, "Port", Integer.toString(mPort));
serverSocketStatus = SocketsManager.ServerSocketStatus.OPEN_NOT_REQUESTED;
defaultClosingRunnable = new Runnable() {
#Override
public void run() {
try {
logger.Warn("Server socket closing automatically at port %s after long delay",
Integer.toString(mPort));
mSocket.close();
serverSocketStatus = SocketsManager.ServerSocketStatus.CLOSED;
closingTime = new Date().getTime();
} catch (IOException e) {
e.printStackTrace();
logger.Error(e, "Failed to close server socket at port %s after delay", Integer.toString(mPort));
}
}
};
explicitClosingRunnable = new Runnable() {
#Override
public void run() {
try {
logger.Debug("Socket closing after delay");
mSocket.close();
serverSocketStatus = SocketsManager.ServerSocketStatus.CLOSED;
closingTime = new Date().getTime();
} catch (IOException e) {
e.printStackTrace();
logger.Error(e, "Failed to close server socket after delay");
}
}
};
}
public void RequestSocketClosingAfterDelay(long delayMills) {
logger.Debug("Close socket after delay %s ms", Long.toString(delayMills));
switch (serverSocketStatus) {
case OPEN_NOT_REQUESTED:
logger.Warn("Closing port that was never opened");
return;
case OPEN_FAILED:
logger.Error("Cannot close a socket that failed to open");
return;
case CLOSED:
logger.Warn("Cannot request closing an already closed socket");
return;
case OPENED:
mHandler.removeCallbacks(defaultClosingRunnable);
break;
case USER_CLOSE_REQUESTED:
logger.Warn("Requested to close a socket that was already requested for closing");
mHandler.removeCallbacks(explicitClosingRunnable);
break;
}
mHandler.postDelayed(explicitClosingRunnable, delayMills);
serverSocketStatus = SocketsManager.ServerSocketStatus.USER_CLOSE_REQUESTED;
}
#Nullable
private ServerSocket RequestSocketForUsage() {
boolean socketIsOpened = true;
switch (serverSocketStatus) {
case USER_CLOSE_REQUESTED:
mHandler.removeCallbacks(explicitClosingRunnable);
break;
case OPENED:
mHandler.removeCallbacks(defaultClosingRunnable);
break;
case CLOSED:
case OPEN_FAILED:
case OPEN_NOT_REQUESTED:
socketIsOpened = tryOpenServerSocket();
break;
}
if (!socketIsOpened) {
serverSocketStatus = SocketsManager.ServerSocketStatus.OPEN_FAILED;
logger.Error("Failed to open the socket server and return it");
return null;
}
// Add back the default closing handler now
mHandler.postDelayed(defaultClosingRunnable, DEFAULT_CLOSING_TIME_MILLS);
serverSocketStatus = SocketsManager.ServerSocketStatus.OPENED;
return mSocket;
}
#Nullable
public Socket accept() throws IOException {
ServerSocket socket = RequestSocketForUsage();
if (socket != null) {
return socket.accept();
} else {
return null;
}
}
public SocketsManager.ServerSocketStatus getStatus() {
return serverSocketStatus;
}
private boolean tryOpenServerSocket() {
int attempt = 0;
do {
++attempt;
try {
this.mSocket = new ServerSocket(mPort);
break;
} catch (Exception e) {
logger.Warn(e, "Failed to start ServerSocket on attempt: %s", Integer.toString(attempt));
synchronized (this) {
try {
wait(DEFAULT_RETRY_TIME_MILLS);
} catch (InterruptedException e1) {
logger.Error("Retry wait() interrupted");
e1.printStackTrace();
}
}
}
} while (attempt < 6);
if (this.mSocket == null) {
logger.Error("Failed to start ServerSocket");
return false;
} else {
logger.Info("ServerSocket started");
return true;
}
}
}
}
----------------------------------------- LATER EDIT -----------------------------------------
I am always triggering the getSocketAtPort() method inside asyncTasks which seems to be part of the problem.
I now opened a socket (using getSocketAtPort()) inside an activity (inside onCreate()) before calling it in asyncTasks. When I do that all the handlers start working (including the ones requested inside the asyncTask). My guess is that the problem has something to do with threading.

unable to fetch process time using sigar

import java.io.IOException;
import org.hyperic.sigar.*;
public class SigarDemo {
public static void main(String args[]) throws SigarException, IOException
{
final Sigar sigar = new Sigar();
final long[] processes = sigar.getProcList();
ProcTime pt=new ProcTime();
for (final long processId : processes) {
ProcUtil.getDescription(sigar, processId);
pt=sigar.getProcTime(processId);
System.out.println("---"+pt.getStartTime());
}
}
I am trying to fetch process time of each process using sigar. I am getting this errors:
Exception in thread "main" java.lang.ExceptionInInitializerError
at taskmanager.SigarDemo.main(SigarDemo.java:22)
Caused by: java.security.AccessControlException: access denied ("java.util.PropertyPermission" "sigar.nativeLogging" "read")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:457)
at java.security.AccessController.checkPermission(AccessController.java:884)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1294)
at java.lang.System.getProperty(System.java:714)
at org.hyperic.sigar.Sigar.(Sigar.java:78)
I have tried policy file setting all permission. but still I am getting errors. I am using netbeans 8.0 . and I had already setting
-Djava.security.manager -Djava.security.policy=src/dir1/dir2/important.policy
I used this code to get the process times
public static void main(String args[]) {
try {
final Sigar sigar = new Sigar();
final long[] processes = sigar.getProcList();
ProcTime pt = new ProcTime();
for (final long processId : processes) {
try {
ProcUtil.getDescription(sigar, processId);
pt = sigar.getProcTime(String.valueOf(processId));
System.out.println("---" + pt.getStartTime());
} catch (SigarException e) {
System.out.println("can't accessible...");
}
}
} catch (SigarException ex) {
ex.printStackTrace();
}
}
you don't want to specify the security policy file in VM arguments to get the process times. but the thing is getProcTime() will not return process times for some process ids because of SigarPermissionDeniedException.
but you will get process time for some processes without any problem.
I got this idea from a sample demo file from bindings\java\examples folder. I posted it below with slight modification. you can compile and run it to see the result(it includes the process time also)
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarProxy;
import org.hyperic.sigar.SigarException;
import org.hyperic.sigar.ProcCredName;
import org.hyperic.sigar.ProcMem;
import org.hyperic.sigar.ProcTime;
import org.hyperic.sigar.ProcState;
import org.hyperic.sigar.ProcUtil;
import org.hyperic.sigar.cmd.Shell;
import org.hyperic.sigar.cmd.SigarCommandBase;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Show process status.
*/
public class Ps extends SigarCommandBase {
public Ps(Shell shell) {
super(shell);
}
public Ps() {
super();
}
protected boolean validateArgs(String[] args) {
return true;
}
public String getSyntaxArgs() {
return "[pid|query]";
}
public String getUsageShort() {
return "Show process status";
}
public boolean isPidCompleter() {
return true;
}
public void output(String[] args) throws SigarException {
long[] pids;
if (args.length == 0) {
pids = this.proxy.getProcList();
}
else {
pids = this.shell.findPids(args);
}
for (int i=0; i<pids.length; i++) {
long pid = pids[i];
try {
output(pid);
} catch (SigarException e) {
this.err.println("Exception getting process info for " +
pid + ": " + e.getMessage());
}
}
}
public static String join(List info) {
StringBuffer buf = new StringBuffer();
Iterator i = info.iterator();
boolean hasNext = i.hasNext();
while (hasNext) {
buf.append((String)i.next());
hasNext = i.hasNext();
if (hasNext)
buf.append("\t");
}
return buf.toString();
}
public static List getInfo(SigarProxy sigar, long pid)
throws SigarException {
ProcState state = sigar.getProcState(pid);
ProcTime time = null;
String unknown = "???";
List info = new ArrayList();
info.add(String.valueOf(pid));
try {
ProcCredName cred = sigar.getProcCredName(pid);
info.add(cred.getUser());
} catch (SigarException e) {
info.add(unknown);
}
try {
time = sigar.getProcTime(pid);
info.add(getStartTime(time.getStartTime()));
System.out.println("this line has executed..!!!");
} catch (SigarException e) {
info.add(unknown);
}
try {
ProcMem mem = sigar.getProcMem(pid);
info.add(Sigar.formatSize(mem.getSize()));
info.add(Sigar.formatSize(mem.getRss()));
info.add(Sigar.formatSize(mem.getShare()));
} catch (SigarException e) {
info.add(unknown);
}
info.add(String.valueOf(state.getState()));
if (time != null) {
info.add(getCpuTime(time));
}
else {
info.add(unknown);
}
String name = ProcUtil.getDescription(sigar, pid);
info.add(name);
return info;
}
public void output(long pid) throws SigarException {
println(join(getInfo(this.proxy, pid)));
}
public static String getCpuTime(long total) {
long t = total / 1000;
return t/60 + ":" + t%60;
}
public static String getCpuTime(ProcTime time) {
return getCpuTime(time.getTotal());
}
private static String getStartTime(long time) {
if (time == 0) {
return "00:00";
}
long timeNow = System.currentTimeMillis();
String fmt = "MMMd";
if ((timeNow - time) < ((60*60*24) * 1000)) {
fmt = "HH:mm";
}
return new SimpleDateFormat(fmt).format(new Date(time));
}
public static void main(String[] args) throws Exception {
new Ps().processCommand(args);
}
}

Establishing WebSocket connection with Java server and Javascript client

I'm trying to implement WebSockets with a Javascript-based client and a Java-based server. I think I've done all the correct steps, but for an unknown reason, I can't establish the connection with both.
When the server socket receives a connection, it handles to form a websocket-accept response, and it sends back to the client, but the connection in the client socket instantly close, weird that there's no handshake problem.
Does anyone have an idea what might be the problem?
Here's my server code implemented in java:
package server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import server.message.Message;
import server.message.SpeakMessage;
public class Server implements ConnectionListener {
private static final int PORT = 1509;
private MessageDispatcher dispatcher = new MessageDispatcher();
private List<ConnectionManager> clients = new ArrayList<>();
public void listen() {
try (ServerSocket server = new ServerSocket(PORT)) {
System.out.printf("Listening on port %d...%n", PORT);
while (true) {
System.out.println("Waiting for connection...");
Socket client = server.accept();
System.out.println("Incoming connection - Attempting to establish connection...");
ConnectionManager manager = new ConnectionManager(client, dispatcher, this);
manager.start();
}
} catch (IOException e) {
System.out.println("Unable to start server");
e.printStackTrace();
}
System.exit(0);
}
public void execute() {
try {
while (true) {
if (dispatcher.isEmpty()) {
Thread.sleep(100);
continue;
}
Message msg = dispatcher.read();
if (msg instanceof SpeakMessage)
broadcast(MessageEncoder.spoke(((SpeakMessage) msg).getText()));
}
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
public static void main(String[] args) {
final Server server = new Server();
new Thread(new Runnable() {
#Override
public void run() {
server.listen();
}
}).start();
server.execute();
}
public synchronized void broadcast(byte[] message) {
for (ConnectionManager client : clients) {
client.send(message);
}
}
#Override
public synchronized void clientConnected(ConnectionManager who) {
clients.add(who);
System.out.println("Connected client " + clients.size());
}
#Override
public synchronized void clientDisconnected(ConnectionManager who) {
clients.remove(who);
}
}
Heres subclass ConnectionManager of server:
package server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.Socket;
import java.security.MessageDigest;
import java.util.Properties;
import server.message.HandshakeMessage;
import server.message.Message;
public class ConnectionManager {
private static final int CLIENT_VERSION = 1;
private Socket socket;
private MessageDecoder decoder = new MessageDecoder();
private MessageDispatcher dispatcher;
private ConnectionListener listener;
public ConnectionManager(Socket connection, MessageDispatcher dispatcher, ConnectionListener listener) {
socket = connection;
this.dispatcher = dispatcher;
this.listener = listener;
}
public void start() {
Thread t = new Thread(new ChannelReader());
t.setName("Client thread");
t.setDaemon(true);
t.start();
}
public void send(byte[] data) {
if (socket == null)
return;
try {
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.write(data);
dos.flush();
} catch (IOException e) {
disconnect("Client closed the connection");
}
}
private class ChannelReader implements Runnable {
private boolean accepted = false;
private String ret = null;
#Override
public void run() {
try {
DataInputStream in = new DataInputStream(socket.getInputStream());
while (socket != null && socket.isConnected()) {
int len = in.readShort();
if (len < 0) {
disconnect("Invalid message length.");
}
String s;
readLine(in);
Properties props = new Properties();
while((s=readLine(in)) != null && !s.equals("")) {
String[] q = s.split(": ");
props.put(q[0], q[1]);
}
if(props.get("Upgrade").equals("websocket") && props.get("Sec-WebSocket-Version").equals("13")) { // check if is websocket 8
String key = (String) props.get("Sec-WebSocket-Key");
String r = key + "" + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // magic key
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.reset();
md.update(r.getBytes());
byte[] sha1hash = md.digest();
String returnBase = base64(sha1hash);
ret = "HTTP/1.1 101 Switching Protocols\r\n";
ret+="Upgrade: websocket\r\n";
ret+="Connection: Upgrade\r\n";
ret+="Sec-WebSocket-Accept: "+returnBase;
} else {
disconnect("Client got wrong version of websocket");
}
Message msg = decoder.decode((String) props.get("Sec-WebSocket-Protocol"));
if (!accepted) {
doHandshake(msg);
} else if (dispatcher != null) {
dispatcher.dispatch(msg);
}
}
} catch (Exception e) {
disconnect(e.getMessage());
e.printStackTrace();
}
}
private void doHandshake(Message msg) {
if (!(msg instanceof HandshakeMessage)) {
disconnect("Missing handshake message");
return;
}
HandshakeMessage handshake = (HandshakeMessage) msg;
if (handshake.getVersion() != CLIENT_VERSION) {
disconnect("Client failed in handshake.");
return;
}
send(ret.getBytes());
accepted = true;
listener.clientConnected(ConnectionManager.this);
}
private String base64(byte[] input) throws ClassNotFoundException,
SecurityException, NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> c = Class.forName("sun.misc.BASE64Encoder");
java.lang.reflect.Method m = c.getMethod("encode", new Class<?>[]{byte[].class});
String s = (String) m.invoke(c.newInstance(), input);
return s;
}
private String readLine(InputStream in) {
try{
String line = "";
int pread;
int read = 0;
while(true) {
pread = read;
read = in.read();
if(read!=13&&read!=10)
line += (char) read;
if(pread==13&&read==10) break;
}
return line;
}catch(IOException ex){
}
return null;
}
}
public synchronized void disconnect(String message) {
System.err.println(message);
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
socket = null;
listener.clientDisconnected(ConnectionManager.this);
}
}
And the MessageDispatcher:
package server;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingDeque;
import server.message.Message;
public class MessageDispatcher {
Queue<Message> messageQueue = new LinkedBlockingDeque<>();
public void dispatch(Message message) {
messageQueue.offer(message);
}
public Message read() {
return messageQueue.poll();
}
public boolean isEmpty() {
return messageQueue.isEmpty();
}
}
And heres my client code implemented in javascript:
var canvas, // Canvas DOM element
ctx, // Canvas rendering context
socket; // Socket connection
function init() {
// Initialise the canvas
canvas = document.getElementById("gameCanvas");
ctx = canvas.getContext("2d");
// Maximise the canvas
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Initialise socket connection
if (window.WebSocket) {
socket = new WebSocket("ws://localhost:1509/", ["1", "YURI"]);
socket.onopen = onSocketConnected();
socket.onclose = onSocketDisconnect();
socket.onmessage = onSocketMessage();
socket.onerror = onSocketError();
} else {
alert("The browser does not support websocket.");
}
};
// Socket message
function onSocketMessage(message) {
console.log('Message: ' + message.data);
};
// Socket error
function onSocketError(error) {
console.log('Error: ' + error.data);
};
// Socket connected
function onSocketConnected() {
console.log("Connected to socket server");
};
// Socket disconnected
function onSocketDisconnect() {
console.log("Disconnected from socket server");
};
I think, it is because you are using the Socket Package on the Java Server Side and the WebSocket API on the Client Side. Your idea is really good but the wrong technology.
Keep the WebSocket on the Client Side (Javascript) becaue you don't have lots of other possibilities, but try JWebSocket on the Server side (Java). In Fact WebSocket is using TCP/IP but its own communication protocol over TCP/IP. The Java Socket Package is purely TCP/IP. Re-write your server with JWebSocket, all details about JWebSocket can be found at:
http://jwebsocket.org/.
I hope my answer will help you.
you must specify end of return packet with "\r\n\r\n"
ret = "HTTP/1.1 101 Switching Protocols\r\n";
ret+="Upgrade: websocket\r\n";
ret+="Connection: Upgrade\r\n";
ret+="Sec-WebSocket-Accept: "+returnBase + "\r\n\r\n";
and for create accept key i use
public class WSKeyGenerator {
private final static String MAGIC_KEY =
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
public static String getKey(String strWebSocketKey) throws
NoSuchAlgorithmException {
strWebSocketKey += MAGIC_KEY;
MessageDigest shaMD = MessageDigest.getInstance("SHA-1");
shaMD.reset();
shaMD.update(strWebSocketKey.getBytes());
byte messageDigest[] = shaMD.digest();
BASE64Encoder b64 = new BASE64Encoder();
return b64.encode(messageDigest);
}
}
I recommend that use the http://websocket.org/echo.html to check the server's websocket functionality

How to check if JZMQ socket is connected

Is there way to check if JZMQ (java binding of zmq) socket is connected?
ZContext zmqContext = new ZContext();
ZMQ.Socket workerSocket = zmqContext.createSocket(ZMQ.DEALER);
workerSocket.setIdentity("ID".getBytes());
workerSocket.connect("tcp://localhost:5556");
After code above I would like to check if workerSocket is connected. It would be nice to check connection status.
No, there's no method in the API to check if a socket is connected.
ZeroMq abstracts the network; client and server connections are completely transparent to the peer making the connection. A client or server may send messages to non-existent peers; no errors will be generated; instead, they'll queue up in socket buffers based on HWM config.
To check for peer availability, do it manually using a synchronous request/reply heartbeat with a timeout factor; here's an example, hope it helps!
Check out samples for request/reply here!
https://github.com/imatix/zguide/tree/master/examples/
i think I found a trick that works for me to check if a socket is connected. The best solution to your client side is to create a socket poller and poll on the pull socket until a message is received. This avoids wasteful sleeps, and makes for generally tighter code:
Here is the code that do the works:
private void blockUntilConnected() {
ZMQ.Poller poller = ctx.createPoller(1);
poller.register(this.subscriber, ZMQ.Poller.POLLIN);
int rc = -1;
while (rc == -1) {
rc = poller.poll(1000);
}
poller.pollin(0);
}
I will also supply the full source code:
Server Part:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;
import java.net.InetSocketAddress;
import java.net.Socket;
import static io.Adrestus.config.ConsensusConfiguration.*;
public class ConsensusServer {
private static Logger LOG = LoggerFactory.getLogger(ConsensusServer.class);
private final ZContext ctx;
private final String IP;
private final ZMQ.Socket publisher;
private final ZMQ.Socket collector;
public ConsensusServer(String IP) {
this.IP = IP;
this.ctx = new ZContext();
this.publisher = ctx.createSocket(SocketType.PUB);
this.publisher.setHeartbeatIvl(2);
this.collector = ctx.createSocket(SocketType.PULL);
this.publisher.bind("tcp://" + IP + ":" + PUBLISHER_PORT);
this.collector.bind("tcp://" + IP + ":" + COLLECTOR_PORT);
this.collector.setReceiveTimeOut(CONSENSUS_TIMEOUT);
this.publisher.setSendTimeOut(CONSENSUS_TIMEOUT);
}
public ConsensusServer() {
this.IP = findIP();
this.ctx = new ZContext();
this.publisher = ctx.createSocket(SocketType.PUB);
this.collector = ctx.createSocket(SocketType.PULL);
this.publisher.bind("tcp://" + IP + ":" + PUBLISHER_PORT);
this.collector.bind("tcp://" + IP + ":" + COLLECTOR_PORT);
this.publisher.setSendTimeOut(CONSENSUS_TIMEOUT);
this.collector.setReceiveTimeOut(CONSENSUS_TIMEOUT);
}
private String findIP() {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress("google.com", 80));
return socket.getLocalAddress().getHostAddress();
} catch (Exception e) {
e.printStackTrace();
}
throw new IllegalArgumentException("Make sure you intern connection is working");
}
public void publishMessage(byte[] data) {
publisher.send(data, 0);
}
public byte[] receiveData() {
byte[] data = null;
try {
data = collector.recv();
} catch (Exception e) {
LOG.info("Socket Closed");
}
return data;
}
public static Logger getLOG() {
return LOG;
}
public static void setLOG(Logger LOG) {
ConsensusServer.LOG = LOG;
}
public ZContext getCtx() {
return ctx;
}
public String getIP() {
return IP;
}
public ZMQ.Socket getPublisher() {
return publisher;
}
public ZMQ.Socket getCollector() {
return collector;
}
public void close() {
this.publisher.close();
this.collector.close();
this.ctx.close();
}
}
Client Part:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;
import static io.Adrestus.config.ConsensusConfiguration.*;
public class ConsensusClient {
private static Logger LOG = LoggerFactory.getLogger(ConsensusClient.class);
private final String IP;
private ZContext ctx;
private final ZMQ.Socket subscriber;
private final ZMQ.Socket push;
public ConsensusClient(String IP) {
this.ctx = new ZContext();
this.IP = IP;
this.subscriber = ctx.createSocket(SocketType.SUB);
this.push = ctx.createSocket(SocketType.PUSH);
this.subscriber.connect("tcp://" + IP + ":" + SUBSCRIBER_PORT);
this.subscriber.subscribe(ZMQ.SUBSCRIPTION_ALL);
this.subscriber.setReceiveTimeOut(CONSENSUS_TIMEOUT);
blockUntilConnected();
this.push.connect("tcp://" + IP + ":" + COLLECTOR_PORT);
}
private void blockUntilConnected() {
ZMQ.Poller poller = ctx.createPoller(1);
poller.register(this.subscriber, ZMQ.Poller.POLLIN);
int rc = -1;
while (rc == -1) {
rc = poller.poll(1000);
}
poller.pollin(0);
}
public void pushMessage(byte[] data) {
push.send(data);
}
public byte[] receiveData() {
byte[] data = subscriber.recv();
return data;
}
public void close() {
this.subscriber.close();
this.push.close();
this.ctx.close();
}
}
Main part: (Notice that the client is first initialized and it's blocked until a server is started and connected. You can simply add a timeout if you don't want to hang on forever)
import java.nio.charset.StandardCharsets;
public class CustomTest {
public static void main(String[] args) {
//client already started and block until server is connected
(new Thread() {
public void run() {
ConsensusClient Client = new ConsensusClient("localhost");
while (true) {
byte[] res = Client.receiveData();
System.out.println(new String(res));
}
}
}).start();
Thread.sleep(3000);
//server started
ConsensusServer Server = new ConsensusServer("localhost");
Thread.sleep(100);
Server.publishMessage("Message".getBytes(StandardCharsets.UTF_8));
Server.publishMessage("Message".getBytes(StandardCharsets.UTF_8));
Server.publishMessage("Message".getBytes(StandardCharsets.UTF_8));
Thread.sleep(10000);
Server.close();
}
}

Categories