Blog stats

This blog has been running for quite a few years now and I got thinking about the traffic patterns on it today in an earlier post, so I thought I’d put some of the info together into a post 🙂

Here are the visits in the last three years (74,000 hits)

And in just the last year (30,000 hits)

The average time on the site remained about the same when looking back one or three years and in both cases is about two minutes.

Here is a world map showing the countries where most of the traffic comes from. The top three were US, India and Canada. The darkest colour represents almost 6000 hits.

The most popular browser with visitors of my site is Firefox, followed by Chrome, IE and Safari. I was a bit surprised that Safari did more poorly than IE, but I guess it can be expected when you see the next figure with OS’s.

The most popular OS’s for my site: Windows, Linux, Mac. This makes me a little sad that Linux wasn’t the highest proportion, given the content of my site…but it was at least respectable.

Lastly, here is the posting frequency. There have been 83 posts total according to the wordpress admin page.

Including Blogs in Tenure & Promotion

Inspired by this blog post: http://andreweckford.blogspot.ca/2012/10/would-you-include-your-blog-in-your-t.html and the ensuing twitter conversation: https://twitter.com/andreweckford/status/260737094056542210 I decided to write a more in-depth response on my blog.

Compared to the rest of the group in the twitter convo, I am probably the most junior being a grad student still (the others are librarians and professors in various stages). The general consensus seems to be that while a forward facing department may consider a blog in their criteria, there are not clear cut rules to support blogs in the process and most people would not include it.

When I get to that stage in my career, however, I’ll try my best to shoehorn it in somehow. I’m of the opinion that any modern academic department should be considering blogs and even social media accounts in the T&P process. These types of things show how engaged an academic is with the public. We need more engaged professors and research students. The general public pays for our work (for the most part) and we should make them aware of what they are paying for.

As mentioned in the twitter conversation, the benefits of blogging and social media alone in terms of connections and collaborations with other researchers end up showing up on the resume anyways with publications and projects. However, I think there is also value in the quality of a blog itself.

As for the less professional posts, I think these also have some value. As long as they aren’t the type someone should be embarrassed about, I think they also still add value. They humanize the professor for the students and the general public and make the professor more approachable. Sometimes its also nice to read these peoples’ opinions on issues outside of their expertise.

My blog has been going for about three or four years now, and while I think the quality of the posts are not as good as the others in the Twitter conversation, it has some value since it has documented some of the journey through grad school, some of the work I’ve done and some of my thoughts that would otherwise just disappeared into the ether. Clearly this is something people are interested in since I regularly get around 2500 hits per month on the site. These types of statistics may be the type of thing to include in T&P files. The number of hits, followers on twitter, retweets, “klout” – all show the level of engagement of the professor. On the other hand, this could just lead to a race to the bottom of constant meaningless social engagement, but I’d still prefer a prof who tweets too much to one who is alone in their bubble.

Upcoming PhD QE Progress

So I’ve been doing my PhD for over two years now, and I haven’t posted a reflective “state of the thesis” post in quite some time, so here it is. I have maxed out my 50 pages (not included ToC and references) for some time now, it’s just been in the process of revision for the last month or so! I have more or less settled on what my research actually is now and am getting a clearer picture of it in my head all the time.

Officially the topic is “Radio Resource Management for Quality of Service in Heterogeneous Wireless Networks”. This is quite the mouthful, I know. Really what it boils down to is: Making various wireless technologies (Bluetooth, WiFi, WiMAX, 3G, 4G, … , etc) seamlessly work together. Many devices are capable of connecting to many of these radio access technologies (RATs), but often it is not seamless. What do I mean by this? Well suppose I am inside a university building, deep in the basement (where they tend to put CS students :P) where there is no mobile reception (3G, 4G etc.). I start downloading a large file, or call someone via wifi. Now I want to walk to my car because it’s time to go home for the day. Many networks now are not able to handle this, and it is interrupted after you change networks. Furthermore, you often have to manually tell the device you want to leave one network and join another. Seamless means this should all happen without you noticing. This is the focus of my research.

The biggest problem that I am concerned with is called handoff or handover. This is when the switch between RATs occurs. Traditionally, this also occurs when a mobile device switches from one tower to another, and it usually involved predicting the motion of the device along with some other factors for Quality of Service (QoS). For a vertical handover, we may or may not need to predict motion. If the heterogeneous wireless network (HWN) is densely covered, many RATs are available throughout the coverage region (as opposed to a sparsely covered where a given location may have access to one technology at once). In a dense HWN, the problem becomes a multi-criteria question.

  1. Which network is most economical for me to connect to?
  2. Which configuration of (network, client) pairs is most profitable for the operator?
  3. Which network is able to provide me with the required QoS?

More technical details to follow…

Tutorial: sockets – 3 ways to listen

As you may know, I have been ta-ing a course in operating systems. We just finished covering sockets and in the last lab I gave a socket demo where I show three different ways a server can listen on a socket. First is a very basic case where the server can only accept and process one connection at a time. Second I show the fork()ing case where multiple connections can be processed concurrently using multiple processes. Lastly, the multiple connection case is handled with select() so that everything can be handled in a single connection.

Single connection server
This server is a basic echo server. A client connects to it on a specific port and enters strings on the stdin. The server maintains the connection until the client terminates the connection with a blank line.

The major weakness of this server is that it can only handle a single connection at once. So if the first connection is very slow, any subsequent connections must wait, even if they are ready to be handled. In the case of this server, the first user to connect may be very slow to type their strings, and even if the second user has already entered a string, it will not be displayed until the first user connection in completed.

#include
#include
#include
#include
#include
#include
#include
#include
#include

#define ERROR(x) do { perror(x); exit(1); } while(0)

#define NAME 257
#define BUFSIZE 257
#define MAXPENDING 1

int main(int argc, char *argv[])
{
unsigned short port; /* Port to which server will bind */
char servhost[NAME]; /* Local host name */
struct sockaddr_in sock; /* INTERNET socket space */
struct hostent *server; /* Local host information */
int S; /* fd for socket */
int NS; /* fd for connected socket */
char buf[BUFSIZE]; /* Input buffer */
FILE *fp; /* Stream (converted file des.) */

if (argc != 2)
{
fprintf(stderr,"usage: server \n");
exit(1);
}

port = atoi(argv[1]);

/*
* Get socket - INTERNET DOMAIN - TCP
*/
if ((S = socket(AF_INET, SOCK_STREAM, 0)) < 0) ERROR("server: socket"); /* * Obtain host name & network address */ gethostname(servhost, sizeof(servhost)); if ((server = gethostbyname(servhost)) == NULL) { fprintf(stderr,"%s: unknown host\n",servhost); exit(1); } /* * Bind to server address - in network byte order */ sock.sin_family = AF_INET; sock.sin_port = htons(port); memcpy(&sock.sin_addr, server->h_addr, server->h_length);

/*
* Bind socket to port/addr
*/
if (bind(S, (struct sockaddr *)&sock, sizeof(sock)) < 0) ERROR("server: bind"); /* * Listen on this socket */ if (listen(S,MAXPENDING) < 0) ERROR("server: listen"); //loop to continue handling connections while(1) { /* * Accept connections. Once connected, the client will be * connected on fd NS, a second and third parameter may be passed * to accept which will be filled in with information regarding the * client connection if desired. * * In this example, once connected the server is done with the * master socket (so closes it). */ if ((NS = accept(S,NULL,NULL)) < 0) ERROR("server: accept"); /* * Using stdio library to read from socket */ if (!(fp = fdopen(NS,"r"))) { fprintf(stderr,">>> Error converting file des. to stream <<<\n"); exit(1); } while (fgets(buf,BUFSIZE,fp)) printf("%s", buf); /* * DONE - simply close() connection */ fclose(fp); close(NS); } return(0); }

fork() - Multiple connection, multiple process
In this case, the server can now handle multiple connections successfully. If the first connection has a long processing time or the user is slow at entering data, the second connection may now continue freely without waiting in line. The downside to this approach is: 1) If the server must handle a large number of connections simultaneously, the server may run out of processes since each connection fork()s. 2) Since a fork() call duplicates variables, file descriptors etc., the server may run out of memory if each connection requires any significant processing.

Notice that the processing portion of the code has been moved into a function which is called when the fork() is executing within the child processes.


Fork Server

#include
#include
#include
#include
#include
#include
#include
#include
#include

#define ERROR(x) do { perror(x); exit(1); } while(0)

#define NAME 257
#define BUFSIZE 257
#define MAXPENDING 1

void handle_connection(int NS);

int main(int argc, char *argv[])
{
unsigned short port; /* Port to which server will bind */
char servhost[NAME]; /* Local host name */
struct sockaddr_in sock; /* INTERNET socket space */
struct hostent *server; /* Local host information */
int S; /* fd for socket */
int NS; /* fd for connected socket */
int pid; /* used to determine parent or child */

if (argc != 2)
{
fprintf(stderr,"usage: fork-server \n");
exit(1);
}

port = atoi(argv[1]);

/*
* Get socket - INTERNET DOMAIN - TCP
*/
if ((S = socket(AF_INET, SOCK_STREAM, 0)) < 0) ERROR("fork-server: socket"); /* * Obtain host name & network address */ gethostname(servhost, sizeof(servhost)); if ((server = gethostbyname(servhost)) == NULL) { fprintf(stderr,"%s: unknown host\n",servhost); exit(1); } /* * Bind to server address - in network byte order */ sock.sin_family = AF_INET; sock.sin_port = htons(port); memcpy(&sock.sin_addr, server->h_addr, server->h_length);

/*
* Bind socket to port/addr
*/
if (bind(S, (struct sockaddr *)&sock, sizeof(sock)) < 0) ERROR("server: bind"); /* * Listen on this socket */ if (listen(S,MAXPENDING) < 0) ERROR("server: listen"); while(1) { /* * Accept connections. Once connected, the client will be * connected on fd NS, a second and third parameter may be passed * to accept which will be filled in with information regarding the * client connection if desired. * * In this example, once connected the server is done with the * master socket (so closes it). */ if ((NS = accept(S,NULL,NULL)) < 0) ERROR("server: accept"); if((pid = fork()) < 0) ERROR("server: fork"); if(pid == 0) { handle_connection(NS); exit(0); } else close(NS); } return(0); } void handle_connection(int NS) { char buf[BUFSIZE]; /* Input buffer */ FILE *fp; /* Stream (converted file des.) */ /* * Using stdio library to read from socket */ if (!(fp = fdopen(NS,"r"))) { fprintf(stderr,">>> Error converting file des. to stream <<<\n"); exit(1); } while (fgets(buf,BUFSIZE,fp)) printf("%s", buf); /* * DONE - simply close() connection */ fclose(fp); close(NS); }

select() - Multiple connection, single process
The last case still has the benefits of fork() but does so in a single process. In this case, select() is used. In this case, each socket descriptor is monitored by select which determines if any of the sockets are ready for I/O. Rather than sitting idly waiting for input on sockets that are not ready, data is processed as it arrives. The drawback to this approach is that it is little trickier to implement and understand, but if you start with a basic case like this it can be quite simple to get the hang of it. When using select(), we need to specify the groups of sockets we wish to monitor. This is done using the fd_set which you can see in the source.


Select Server

#include
#include
#include
#include
#include
#include
#include
#include
#include

#define ERROR(x) do { perror(x); exit(1); } while(0)

#define NAME 257
#define BUFSIZE 257
#define MAXPENDING 1

void handle_connection(int NS, fd_set * activefds);

int main(int argc, char *argv[])
{
fd_set readfds, activefds; /* the set of read descriptors */
unsigned short port; /* Port to which server will bind */
char servhost[NAME]; /* Local host name */
struct sockaddr_in sock; /* INTERNET socket space */
struct hostent *server; /* Local host information */
int S; /* fd for socket */
int NS; /* fd for connected socket */
int i; /* counter to go through FDs in fdset */

if (argc != 2)
{
fprintf(stderr,"usage: select-server \n");
exit(1);
}

port = atoi(argv[1]);

/*
* Get socket - INTERNET DOMAIN - TCP
*/
if ((S = socket(AF_INET, SOCK_STREAM, 0)) < 0) ERROR("select-server: socket"); /* * Obtain host name & network address */ gethostname(servhost, sizeof(servhost)); if ((server = gethostbyname(servhost)) == NULL) { fprintf(stderr,"%s: unknown host\n",servhost); exit(1); } /* * Bind to server address - in network byte order */ sock.sin_family = AF_INET; sock.sin_port = htons(port); memcpy(&sock.sin_addr, server->h_addr, server->h_length);

/*
* Bind socket to port/addr
*/
if (bind(S, (struct sockaddr *)&sock, sizeof(sock)) < 0) ERROR("server: bind"); /* * Listen on this socket */ if (listen(S,MAXPENDING) < 0) ERROR("server: listen"); /* Initialize the set of active sockets. */ FD_ZERO (&activefds); FD_SET (S, &activefds); while(1) { /* Block until input arrives on one or more active sockets. */ readfds = activefds; if (select (FD_SETSIZE, &readfds, NULL, NULL, NULL) < 0) { perror ("select"); exit (EXIT_FAILURE); } /* Service all the sockets with input pending. */ for (i = 0; i < FD_SETSIZE; ++i) { if (FD_ISSET (i, &readfds)) { if (i == S) { /* Connection request on original socket. */ /* * Accept connections. Once connected, the client will be * connected on fd NS, a second and third parameter may be passed * to accept which will be filled in with information regarding the * client connection if desired. * * In this example, once connected the server is done with the * master socket (so closes it). */ if ((NS = accept(S,NULL,NULL)) < 0) ERROR("server: accept"); FD_SET(NS, &activefds); //add the new socket desc to our active connections set } else { /* Data arriving on an already-connected socket. */ handle_connection(i, &activefds); } } } /* //end of for */ } /* //end of while */ return(0); } void handle_connection(int NS, fd_set * activefds) { char buf[BUFSIZE]; /* Input buffer */ FILE *fp; /* Stream (converted file des.) */ /* * Using stdio library to read from socket */ if (!(fp = fdopen(NS,"r"))) { fprintf(stderr,">>> Error converting file des. to stream <<<\n"); exit(1); } //if fgets fails we have end of line, quit if(!(fgets(buf,BUFSIZE,fp))) { /* * DONE - simply close() connection */ fclose(fp); close(NS); FD_CLR(NS, activefds); } else printf("%s", buf); }

Additional Information
http://www.uoguelph.ca/~jernst/3110/cis3310-lab4.pdf
http://www.socs.uoguelph.ca/~dbm/teaching/CIS3110/
http://beej.us/guide/bgnet/
manpages!

Updates: Publications, Guelph ACM, Teaching, Thesis

Just a short post with some updates since I’ve been quite busy as usual.

I have submitted the final draft of an adaptive scheduling algorithm for wireless networks to BWCCA conference in Japan. I intend to present my findings in November.

The ACM Group I am chair of is organizing a computer programming contest at Guelph for the fall semester. We are also planning to try to field a team for ACM ICPC* Update * We have been featured in the ACM student publication crossroads: http://tinyurl.com/25u5vxt.

A few days ago I found out I am the teaching assistant for CIS2030 at Guelph for the second time! I am excited to be back, and expect to do a good job since I am becoming familiar with the course.

Lastly, my thesis has been progressing slowly this semester. I am still in the stage where I am deciding where to focus my work. The general area I am exploring is heterogeneous wireless networks, however there are many problems and it is difficult to choose one to focus on. Since I worked in scheduling for my MSc. thesis, I intend to move in a bit different of a direction so that I expand my knowledge. (although I still may publish some more scheduling papers since I still have some ideas in that area)