Showing posts with label server. Show all posts
Showing posts with label server. Show all posts

09 October, 2015

Java Programming Tutorial - Unit 0 - The Basics

Unit 0?  If you're new to this world, it might seem odd, but you'll see why we start 0.  If not, well you probably might skip this post for now.

If you decided to stay and read on, then welcome to the world of computer programing, where media reports are exaggerated and computers are very dumb ;)

A brief intro to programming

Cheesy Java code
Programming is "the act of instructing computers to perform tasks".  Computers don't get it when you tell them "write text".  What they do understand however is a series of bits, which ultimately lead to the text being written.

I'm not going into the great detail about the origins of programming, however the following is a very brief overview to put you in context.

The first computer programs consisted primarily of punch-card.  These were the earliest forms of bits, holes to represent 'on' or '1' and solid wood for 'off' or '0'.  As time went by, digital valves were used and nowadays we use semiconductors and integrated chips.  The concept has remained the same though.  Writing ones and zeros is of course complex, so much so that no one has ever actually programmed in ones and zeros.  What they did do was devise a system to write meaningful text and then convert it to ones and zeros.  For example, the earliest code, in Assembly Language, would have looked like this



It is complicated, unless you're an engineer in the 50's (although it's fair to note that it is still used today for very specific reasons).  The development of programming languages was just like this exact case.  A language becomes too unwieldy (projects gets larger and reaches the practical limitations of the language), so a new higher level language is created to cater for new features.

The next language then uses a single command to represent a group of lower level commands.  As you might expect, it is vastly more complex than just wrapping the lower level, but you get the idea.  A tool that converts the high level language to the lower level is called a compiler.

Once computers became mainstream, more and more different kinds of architectures were created.  An architecture is a CPU design which usually has its own machine language (the way 1's and 0's are organised for it to understand). As each CPU typically understood different instruction sets, different compilers were written to "wrap" architecture-dependent code.


Now the next problem was that it's not as simple as writing the code once and compiling it for each architecture.  The code usually had to be modified for each system it was intended to run on, so portability was lost.  Having a large project would render this process impractical so a new language came along that tried to solve this problem once and for all.

Java

Java was a language developed in 1995 by what was once Sun Microsystems (now Oracle).  What's interesting about Java is that it is much more than just a language.  Java is a whole ecosystem, having the language syntax, compilers, environments, SDK and community.

Duke, the Java mascot
But how did it solve the portability issue?  As I mentioned, it is a whole ecosystem so there is a more elaborate system at play.  What Sun did was create a language that is then compiled to a byte code rather than machine code.  This byte code is then executed by the Java Virtual Machine (so, yes, it's still machine code, but a different kind of machine).  This JVM is the only part which is differently coded and compiled depending on the architecture.  

So we now have a language which can be written and compiled just once and being confident that it will run on any kind of CPU as long as the JVM exists for that CPU.  This VM is also known collectively as the Java Runtime Environment (JRE), of which the byte code interpreter plays a major role.

Along the years Java was prominent on the web in what are knowns as applets.  Nowadays with the emergence of HTML5 and JavaScript (which has a relation of 0% to Java, so don't get confused), applets have become a thing of the past.  Java is also popular on desktop applications, mobilephones, TV set top boxes, DVD players, etc.

Java today

Java has a very strong community and many standards go through what are known Java Specification Requests (JSRs ), much like Request For Comments (RFCs) if you're familiar with network protocols.  Basically this is a process for definitions of ideas, standards, protocols, etc.

Through this process, Java has become arguably one of the top languages for high end websites (technically known as web apps).  Twitter for example, runs on Java, so you get the idea of the strength of Java.  Throughout this series we shall cover, quite in depth, how to write enterprise web applications in Java.

Java used to, and still does in a revived way, dominate the mobile aspect to.  This sheer adaptability, from top range servers to mobile phones, without doubt, makes Java the most versatile language ever.  In the early days of smartphones, Symbian was the king of mobile operating systems.  It used to run a version of Java known as J2ME (Mobile Edition).  Today the Operating System with the largest active user base is Android.  Surprise surprise, apps written for this OS are also in Java and use almost the exact same tools - it's a bit more complex - but we'll see as we go along  how seamless it is to adapt your Java code to it.


Next Steps

So now you have a very basic idea of what programming is and how Java relates to it.  Of course, a lot more resources can be found elsewhere if you're interested in more history and details.  Wikipedia is one of those sites so you can head over there to further whet your appetite.

Following this post we shall start off with a basic Java environment set up; from the quick installation to your first Hello World! 

01 October, 2015

HDMI over WiFi

No not really, no such thing exists.  Well you can stream HD media over WiFi but not in a plug and play way as a common HDMI cable.  There are various ways this can be accomplished but the idea is simple;  run a server from a device and play it on another, as long as there is a protocol, typically DLNA.



Recently I came across a new video format which looks quite interesting and powerful.  HEVC was released a few months ago (only drawn up sometime in 2013) and is now gaining traction.  I was surprised to find that an hour long HD video can be compressed down to 200 megabytes or so.  Being so new not many players can really decode it, as expected.  If you're on Linux, great news! It's not so hard to get it to play.  As always, VLC is your best friend so the solution I have/found is for VLC.  All that's needed is a new library from a PPA and you're good to go.

sudo apt-add-repository ppa:strukturag/libde265
sudo apt-get update
sudo apt-get install vlc-plugin-libde265

That takes no more than a few seconds; minutes if you're on a slow connection (which makes the HEVC format ideal in your case).

I wrote this little post about this format because I am quite interested in how the far we can compress HD videos, but also because it was a bit inconvenient for me to not be able to play it pretty much anywhere (BubbleUPnP and chromecast appear to handle it though).  It may spare you some time hunting for a way to watch that latest episode next time :)  Yet still, my original thought (and title) of this post were actually meant for something totally different, but hey, two birds one stone!

I need to learn to HDMI
Having organised cables is quite important if you intend to keep your sanity.  Not long ago I did rewire my homelab and after a few hours everything look perfectly in place.  Except for one thing; WiFi.  It was constantly disconnecting and apparently going offline and back again for no apparent reason.  Restarting, re-configuring and switching ports fixed nothing.

A few hours or days go by and I started noting red pixels showing up on my screen at particular points where the image was darker.  Then it hit me.  There must have been some interference between my WiFi router and the HDMI cable in its vicinity (hence the title ;)).  Looking around on the internet seemed to prove my theory, even though similar cases appeared to be quite uncommon.  I have not completely fixed it yet however messing around with the cable is a good workaround.  That's until the shielded HDMI cable arrives in my mailbox, which should hopefully fix the issue.


20 December, 2011

Remote Desktop Viewer - The cheap way [Part 1]

Microsoft RDP, RemoteFX, VNC.  That is the real stuff.  Solutions such as those will allow you to secure your connections, log you in to your desktop, compress the connection, etc.  But have you ever thought if it is possible to implement something rudimentary, totally in Java.  Actually it is possible.  But it's nothing much, and what I'll be doing here is a very, very basic implementation of an idea.  Obviously one can go on and enhance it, but it's almost totally impossible to produce a real solution, since Java does not have direct access to the OS, so for example you cannot remotely log-in, as you would for example using ssh.  Well it might be possible, but it would be an overkill.

As I said, I will simply implement an idea, so even though I know we won't be building the next Remote Desktop protocol, it is still interesting.

First we shall lay out some basic requirements.  Basically we will build a server and a client.  The server shall receive a request, it will then grab a screen shot, and send it back.  Meanwhile the client will wait for the server to reply with the image, and will then draw it.  This will go on until we disconnect.

So create three packages first, com.jf.rd, com.jf.rd.client and com.jf.rd.server.  Obviously you can name them whatever you want, but ideally you should have xxx.xxx.client and .server.

We'll start off with the server.  That way we can define what we expect from the client and what we intend to send back.

Now, in the server package create the JRDServer class.


package com.jf.rd.server;




public class JRDServer
{
public static int PORT;

public static String USER;
public static String PASS;

/**
* Parameters:
* Port, User, Password
* @param args
*/
public static void main(String[] args)
{
if (args.length < 3)
{
System.out.println("Usage: JRDServer Port User Password");
System.exit(0);
}

PORT = Integer.parseInt(args[0]);
USER = args[1];
PASS = args[2];

System.out.println("JRD Server sdtarted.  Will listen for connections on " +
"port " + PORT);

JRDServer server = new JRDServer();

server.start();
}

private ConnectionListen listen;

public JRDServer()
{
this.listen = new ConnectionListen(this);
}

public void start()
{
System.out.println("Service Thread starting...");
listen.startServer();
Thread srv = new Thread(listen);
srv.start();
}

public void stop()
{
System.out.println("Service Thread stopping...");
listen.stopServer();
listen.destroy();
}
}


This class is basically an entry point to the server.  I expect some basic Java knowledge so I will describe this only briefly.  We start the server by passing 3 arguments; the port to which we will bind, a username and a password.  The port is the real necessity, and as yet the user and password will not be really used, and will be there so that one day we can implement some sort of security.

There are also the start and stop methods.  start will initialise a listener class which will be running on a separate thread.  That way we can serve our clients in a parallel fashion and also prevent any user from blocking us to the rest of the application in a manner which will stop us from stopping the server.

stop simple stops the listener class and releases its resources.

Next up is the listening class.  This class will loop while the server is running and every time a connection is requested, an other, separate thread is created and the client is served.


package com.jf.rd.server;


import java.io.IOException;
import java.net.ServerSocket;


public class ConnectionListen implements Runnable
{
private boolean running;
private ServerSocket serv;

public ConnectionListen(JRDServer server)
{
try
{
serv = new ServerSocket(JRDServer.PORT);
}
catch (IOException e) 
{
System.err.println("The ServerSocket could not be initialised.");
System.err.println("Reason : " + e);
}
}

public void startServer()
{
running = true;
}

public void stopServer()
{
running = false;
}

@Override
public void run()
{
while (running)
{
try
{
Connection conn = new Connection(serv.accept());
Thread tr = new Thread(conn);
tr.start();
}
catch (IOException e) 
{
System.err.println("A connection could not be accepted.");
System.err.println("Reason : " + e);
}
}
}

public void destroy()
{
try
{
serv.close();
}
catch (IOException e) 
{
System.err.println("The ServerSocket was not closed.");
System.err.println("Reason : " + e);
}
}
}


This time, a server socket is passed as a variable to the constructor. This is the socket which will listen for and accept connections.  The run method, which is the implementation of the Runnable class is what will be running on a separate thread.  Therefore we can simply put a while loop and, kind of, forget about it, since it won't be blocking us (the main thread).  It shall keep on looping until the running flag is false.  So when we start the server we must set running to true and then start it.  To stop it - well - set it to false, and the looping will stop.

Of course, if we won't be listening for any more connections, we should close the server socket.

Finally, the Connection class is created.  Once this is done, the server is basically complete.  Now I should explain what will happen when this is actually run.  Any client that shall connect to this server will receive a byte stream resulting from a screenshot.  It is irrelevant if the client is a web browser, a mobile app or a simple socket.  Also, we won't be checking what the client is actually requesting, so as you can see, the username and password are irrelevant.   That means that you should either practice, and implement an authentication system (easily done) or simply avoid running this server if you fear someone might connect to it and, sort of, spy on you (aye, this is easier).

So, to the connection class.

package com.jf.rd.server;


import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.Socket;


import javax.imageio.ImageIO;


public class Connection implements Runnable
{
private static final int IMG_WIDTH  = 960;
private static final int IMG_HEIGHT = 600;

private Socket connSock;
private static final int BUF_SIZE = 2048;
static final byte[] EOL =
{ (byte) '\r', (byte) '\n' };
private byte[] buf;


public Connection(Socket connSock)
{
this.connSock = connSock;
buf = new byte[BUF_SIZE];
}


@Override
public void run()
{
try
{
InputStream is = new BufferedInputStream(connSock.getInputStream());
PrintStream ps = new PrintStream(connSock.getOutputStream());


for (int i = 0; i < BUF_SIZE; i++)
buf[i] = 0;


int nread = 0, r = 0;


outerloop: while (nread < BUF_SIZE)
{
r = is.read(buf, nread, BUF_SIZE - nread);
if (r == -1) return;
int i = nread;
nread += r;
for (; i < nread; i++)
{
if (buf[i] == (byte) '\n' || buf[i] == (byte) '\r')
break outerloop;
}
}


System.out.println("Done reading.");


Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Rectangle screenRectangle = new Rectangle(screenSize);
Robot robot = new Robot();
BufferedImage image = robot.createScreenCapture(screenRectangle);
int type = image.getType() == 0? BufferedImage.TYPE_INT_ARGB : image.getType();
image = resizeImage(image, type);

ImageIO.write(image, "JPG", connSock.getOutputStream());


ps.flush();


connSock.close();
}
catch (Exception e)
{
System.err.println("Error, somewhere...");
e.printStackTrace();
}
}


private static BufferedImage resizeImage(BufferedImage originalImage,
int type)
{
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
g.setComposite(AlphaComposite.Src);
 
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
 
return resizedImage;
}


}


There it is then.  The Main screen grabber and sender.  We're not doing much here;  just receiving a request and then write "Done reading" when the process finishes, and then a picture is sent.  The resizeImage method is used to reduce the size of the image so that we do not send an image the size of your screen resolution.  That would be slow and besides, you can also specify what "resolution" you intend to receive.  The socket is also closed here, that's important too.  The lines between printing "done reading" and ImageIO.write are grabbing the screen using the AWT (Advanced Window Toolkit), so what this means is that you must have an OS that supports GUI (i.e. not headless, as it is known) and you must be logged in basically, since it grabs the screen as seen by the current user.  Therefore apart from the fact that we cannot remotely login, we also can't turn off the video card.  You can turn off the screen, obviously (lol).

That was part one of this, erm, tutorial, or whatever it is.  I like doing these sort of mini programs when I am trying to solve other problems, that's why they are not at the bleeding edge of technology.  And then, when I'm done, I just write something about it, maybe someone out there learns something hehe.

The next thing we'll do, is build a client application.  I currently plan on supporting only viewing, but eventually, we might spice it up a bit by adding cursor support so that you may click on the client and it will then be forwarded to the server and eventually consumed by the OS that is hosting the server.

Also, the second part will probably come out either just before 2012, or probably in the first week of January, so until then, Merry Christmas and a Happy New Year! :D