Showing posts with label sockets. Show all posts
Showing posts with label sockets. Show all posts

Sunday, 30 March 2014

Google App Engine - First try

Introduction

I own an Internet-enabled digital scale for weighing myself and measuring my impedance.

Architecture

Functional Requirements (FR):
  • I wish to store a backup of my scale measurements, for my own purposes
  • however, scale measurements must continue to be reported to the official website
I have several Non-Functional Requirements (NFR):
  1. needs to use Java (because that's what I do)
  2. the scale receiver uses a simple unencrypted proprietary protocol
  3. the program receiving data from the scale receiver can handle raw sockets (related to previous point)
  4. must scale easily
  5. must not cost any money (until a certain threshold of users is reached, obviously)
  6. must provide decent monitoring
  7. needs to have an extremely low amount of maintenance
  8. must be able to easily create/upgrade/extend the part that uses those measurements for stuff, without disrupting the core functionality of receiving measurements
  9. needs to have the Cool Tech Factor™
These dictate which kind of architecture to use:
  1. Google App Engine (NFR 1, 4, 5, 6, 7, 8 but fails 2 and 3, definitely allows for NFR 9)
  2. a simple socket server, receives measurements, sends them on to Google App Engine and the original website (NFR 2, 3, 5, 7, might fail 4 and 8, but perhaps not if we keep the amount of actual work done by the simple socket server to a minimum, definitely fails NFR 9)

Implementation

The "Daemon3" sends the results to the Google App Engine2, using a Java library1 to make a HTTP POST request.

Example of Use

In the upper-right corner of my blog, my current weight is visible. It is a first example of what is possible.

I am planning on providing, on my blog, a complete graph of my weight over time. Stay tuned.

For the "Daemon" in the picture, that is the socketproxy server I made first. See [3].

References

[1] Apache HTTP Components
https://hc.apache.org/
[2] Google App Engine
https://developers.google.com/appengine
[3] SocketProxy Server
http://randomthoughtsonjavaprogramming.blogspot.nl/2014/03/socketproxyserver.html

Tuesday, 4 March 2014

SocketProxyServer

I recently had a need to check out the communication between a client and a server, as well as act upon the contents. Now, I could have used a Network Sniffer to find that out, but it's hard to have a hook with a Network Sniffer and a Java program. Besides, the level of detail is a bit too high. I was only interested in what data is actually going over the line.

With this in mind, I set about to write my "socket proxy server".

The main reason for this "socket proxy server" is because I both do not control the client and the server, yet I wish to "be involved". One saving grace is that I can change the server IP address on the client.

I tested my socket proxy server by starting it as a proxy to a simple website.

java -cp socketproxy.jar com.tools.socketproxy.Main 8080 www.karchan.org 80

So, now I could connect to http://localhost:8080 and I would see the website provided.

Here is the communication as the socket proxy server saw it. First the messages as sent by the client.
received from client:{GET / HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:27.0) Gecko/20100101 Firefox/27.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: has_js=1
Connection: keep-alive
If-Modified-Since: Wed, 26 Feb 2014 16:26:34 +0000
If-None-Match: "1393431994"

}
Consequently the reply from the server.
received from server:{HTTP/1.1 200 OK
Date: Wed, 26 Feb 2014 16:29:04 GMT
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.3.3
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Last-Modified: Wed, 26 Feb 2014 16:29:04 +0000
Cache-Control: no-cache, must-revalidate, post-check=0, pre-check=0
ETag: "1393432144"
Link: </node/1>; rel="canonical",</node/1>; rel="shortlink"
X-Generator: Drupal 7 (http://drupal.org)
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8

26a5
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
  "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" version="XHTML+RDFa 1.0" dir="ltr"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:dc="http://purl.org/dc/terms/"
  xmlns:foaf="http://xmlns.com/foaf/0.1/"
...


The UML diagram above, shows the main Thread classes and how they relate to each other.

Dealing with multi-threaded programming is always hard and dangerous. In our case, the threads are provided by a fixed thread pool in the concurrency package of Java. I also had a List of Messages, so the list was created using Collections.synchronizedList(List list). What helps is that two connections cannot interfere with each other, making threading easier.

You can find the source code (Java 7) and javadoc in the references below.

Currently the functionality is limited, however it should be easy to extend.

For example, the current listener will only be called after the conversation has finished. This makes the current implementation unsuitable for directly interfering in the communication.

I required this socket proxy server for one of my private hobby projects. This will be the subject of one of my next blog posts. See [1].

References

Github - socketproxy repository
https://github.com/maartenl/socketproxy
Github - socketproxy javadoc
http://maartenl.github.io/socketproxy/javadoc/
[1] Google App Engine - First Try
http://randomthoughtsonjavaprogramming.blogspot.nl/2014/03/google-app-engine-first-try.html