Intro to Network Programming – Part 2 – TCP Protocols

This is the second post in a series of posts on Network Programming.

For the first part of the series click here.

In the first post we introduced UDP and TCP sockets, showed how to create server sockets, bind them to an address, and showed what happens when a message is too long to be read in a single call to socket.recv.

Recall that the first time we had our client talk to our server we had it send “the rain in spain stays mainly in the plain” which is only 43 characters long, but the server was listening for 100 characters.   This is because (per the documentation) the 100 we are passing into the recv method is the maximum number of bytes to read.

So how do we receive a message that is more than 100 bytes?   It’s easy we make additional calls to socket.recv.

#!/usr/bin/env python

from __future__ import print_function
import socket


def main(*args, **kwargs):
    print('creating server socket')
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print('done. now binding to address')
    server_socket.bind(('0.0.0.0', 54321))
    print('done. now listening for connections')
    server_socket.listen(20)
    try:
        while True:
            client_socket, client_address = server_socket.accept()
            print('new client connected from: ', client_address)
            needs_to_keep_reading = True
            while needs_to_keep_reading:
                content = client_socket.recv(100)
                print('#### new data received ####')
                print(content)
                needs_to_keep_reading = len(content) == 100
            print('#### finished receiving data ####')
            client_socket.shutdown(socket.SHUT_RDWR)
            client_socket.close()
    finally:
        server_socket.shutdown(socket.SHUT_RDWR)
        server_socket.close()


if __name__ == '__main__':
    main()

So here we keep reading while we receive exactly 100 bytes.

Great!!!

Unfortunately, this won’t work in the real world. What we didn’t mention earlier was that we can’t control how many bytes are recieved. Even if the client on the far side does indeed send exactly 150 bytes in a single socket.send command, that doesn’t mean that two calls to socket.recv(100) will return the first 100 bytes followed by the second 50 bytes. This is because those bytes may be split up along the way as they travel throughout the internet.

This sample client program is contrived, but shows that you can’t count on always reading the maximum 100 bytes, even if more than 100 bytes are headed your way.

#!/usr/bin/env python

from __future__ import print_function
import socket


def main(*args, **kwargs):
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect(('0.0.0.0', 54321))
    total_stuff = 'banana'*100
    first_send = total_stuff[:20]
    second_send = total_stuff[20:]
    client_socket.send(first_send)
    client_socket.send(second_send)
    client_socket.shutdown(socket.SHUT_RDWR)
    client_socket.close()


if __name__ == '__main__':
    main()

So crud. How do we know when “the message” has ended.

This is what network protocols are for. Before we talk about what a network protocol is, we should dig in to understand what a protocol is. I think the simplest example of a protocol is Morse Code. Morse Code was a simple agreement between all parties using Morse Code on how to represent letters and numbers. It also said how to separate words (seven units of silence indicates the separation of a word). However, because it had no way of representing a period or other punctuation, there was no way of indicating the end of a sentence. That’s why, when ever you see people doing Morse code in historical TV shows they are always saying STOP, blah blah blah STOP.

The word STOP was used informally as a means of indicating the end of a sentence.

Network protocols behave the same way, in HTTP a “message” is either an HTTP request or an HTTP response but both end with two carriage return line feeds CF LF CR LF. So and HTTP server must continue to read on the socket until it comes across two carriage return line feeds. But what happens if that sequence of characters never occurs? Well, that probably is an indication of either a buggy or malicious http client (or server) and typically server implementations might limit how large a message can be (if the protocol standard doesn’t explicitly state how to handle this type of situation).

There are two main ways of indicating the end of a message. One would be to state that all messages are of a certain length. The other would be to implement some sort of delimited indication that the message has ended. Using STOP with morse code and two carriage return line feeds imply that these protocols are both delimited.

Naturally, a delimited protocol is more flexible than a fixed size one, but there is no doubt that a fixed length protocol is easier to implement (no need to scan the content of the message to seek for delimiters).

So we’ll finish off this post by creating a simple echo server and echo client. The echo server will accept client sockets and it will read in as much data from the client as possible until it gets to a colon character (:). Once it sees the colon it will send back whatever the client sent (including the colon) back to the client. Once the data has been sent it will start over, reading more data from the client until it sees another colon and sending that back to the client. The server will continue in this fashion until the client closes the connection.

In our client we will allow the user to enter as much data as the user wants then send the data to the server. After it sends the data to the server it will read everything back from the server and then ask the client for more info.

Now before we get coding on this we have to address the scenario on the server when the client disconnects. How do we know when the client disconnects? From this article in the python documentation, socket.recv returns zero bytes it means that the other end has closed the connection.

So here’s our server program now:

#!/usr/bin/env python

from __future__ import print_function
import socket


def main(*args, **kwargs):
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(('0.0.0.0', 54321))
    server_socket.listen(20)
    try:
        while True:
            client_socket, client_address = server_socket.accept()
            handle_client(client_socket)
    finally:
        server_socket.shutdown(socket.SHUT_RDWR)
        server_socket.close()

def handle_client(client_socket):
    socket_is_alive = True
    while socket_is_alive:
        complete_content = ''
        needs_to_keep_reading = True
        while ":" not in complete_content:
            current_chunk = client_socket.recv(100)
            complete_content = complete_content + current_chunk
            if len(current_chunk) == 0:
                print('---the socket died---')
                socket_is_alive = False
                break
        print('---got full message---')
        print(complete_content)
        print('---end of message---')
        if socket_is_alive:
            print('---sending the echo---')
            client_socket.send(complete_content)
            print('---done echoing---')


if __name__ == '__main__':
    main()

and here’s our client program.

#!/usr/bin/env python

from __future__ import print_function
import socket


def main(*args, **kwargs):
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect(('0.0.0.0', 54321))
    data_to_send = ''
    try:
        while True:
            data_to_send = data_to_send + raw_input('enter more data:') 
            if ':' in data_to_send:
                client_socket.send(data_to_send)
                data_to_send = ''
                print_received_data_from(client_socket)
    except KeyboardInterrupt:
        client_socket.shutdown(socket.SHUT_RDWR)
        client_socket.close()

def print_received_data_from(client_socket):
    complete_data = ''
    while ':' not in complete_data:
        complete_data = complete_data + client_socket.recv(100)
    print('got data back')
    print(complete_data)
    print('done getting data')

if __name__ == '__main__':
    main()

Go ahead and run them both and notice how the server can detect when you close the client program by pressing control-c.

But try running two clients at the same time. You should notice that the second client won’t receive any data from the server until the first client stops. This makes sense because socket.accept on line 13 of the server doesn’t get called again until the last client has been handled.

So how can we support multiple clients at the same time? Well there are lots of ways to do that, but we’ll leave that for part 3 of the series.

Sharpening your Axe

There’s a famous quote by Abraham Lincoln that reads, “Give me six hours to chop down a tree and I will spend the first four sharpening the ax.”  What good ol’ Abe was trying to communicate with this saying is that proper preparation is key to successfully completing a task. Not only will sharpening the blade require you to assemble the necessary tools, it also saves you work when it comes time to chop down the tree.

I often think of this old adage when I am given a new report to build or feature to develop.  Instead of an axe, the tool I have to sharpen is my brain and instead of chopping down a tree, I am building software.  I am often tempted to start writing queries and assembling data before I even have a firm grip on the core of the problem.  I remember when I first started writing software, I would start furiously typing out queries and tests only to realize I was writing code that didn’t directly fix the initial problem.

Thankfully, there have been others who suffered from this lack of preparation who studied development cycles and established best practices for proper software development.  Some of the leading software development practices today are Agile, Waterfall and TDD (test driven development).

Most of the development cycles take root in waterfall which illustrated a cascading model of processes, in which progress is achieved through flowing downwards through some core main stages: requirements, specifications, design, implementation, verification, maintenance.

The waterfall methodology is appealing because specifications and designs can be created before implementation begins.  Waterfall is great concept as long as both the problem and solution are well known.  With this flow, the waterfall almost becomes an assembly line and code can be written easily.   If Abe were following the Waterfall methodology, he would have spent the first 3 hours buying the best ax, sharpening it and looking up effective youtube tutorials on how to swing an ax.  The next 3 hours would have been spent chopping down the tree.

Although waterfall provides a very clear road map to a successful launch, what happens when the solution isn’t 100% understood before development beings?  What happens when the designs and specifications made in steps two and three end up being poor choices?   For our analogy, what if Abe sharpened his ax incorrectly or discovered the YouTube video showing best chopping techniques was horribly inaccurate?

Enter the Agile Product Development Cycle.  The Agile Development Cycle starts with user stories as the driving force behind production.  Filling in the phrase, “As a ____ user, I want to ______” gives developers a clear understanding of the end goal.  In addition to starting with a customer first mindset, agile incorporates feedback loops that include testing, bug fixes and release planning.  The agile methodology takes the best part of waterfall development but starts with a solution-first approach that challenges developers to sharpen before building, test before striking and the freedom to readjust after every swing.

The Fractal Nature of Software Development

One of the very first things you learn as a programmer is that you can’t comprehend every part of a system (at least, not at the same time.) Like with many other complex tasks, we break programming down into simple chunks which we can tackle mostly without concerning ourselves with the intricacies of the rest of the system. What these chunks are varies with specific needs and circumstances, but they are, all the same, bits of problem-space we’ve abstracted away, to be solved and then re-integrated into the final product.

The important thing to note is that this abstraction doesn’t just stop at one step. Each time we break off a conceptual piece of the puzzle, we do the following:

  • See if we can break down that chunk into sub-chunks.
  • Hook those subchunks together so that the chunk works as a whole.

What’s interesting is that, for the most part, systems design is entirely about putting off the work of ‘implementing’ a chunk, such that eventually, that need disappears. When we fully expand a system, breaking down each piece into progressively smaller parts, what we find is that the real software – the stuff that does the work – is the structure.

But what does that imply for us, as people who create these systems? It means that we need to think carefully about the way we structure our system – the way we break it down into chunks. Too few chunks and you aren’t letting structure handle any of your burden – you may be duplicating code that you could easily factor out into its own chunk; too many chunks and it may be difficult to climb back up the conceptual tree and hook everything together.

It also means that we need to spend time mapping out a project before we dive in, lest we find ourselves neck-deep in shark-infested waters. A little goes a long way, though. It’s not impossible to make these jigsaw pieces fit together, and when they do, you’ve created software that will last.

Passwords: Keep them secret, keep them safe

The use of passwords dates back to ancient times, where they existed as verbal or written phrases that a group would use to verify its members’ identities. Their use has evolved and become more complex since then – it was not until the rise of the personal computer that use of a password to safeguard a user’s personal information would be truly feasible, and even then most users would only have a single password at a time. As any reader of this post will already know, that has changed considerably since the advent of the internet.

With most websites requiring passwords for membership, it is no longer uncommon for a person to need to remember a plethora of different passwords at all times. This is harmless so long as that person has either an excellent memory or unending patience – without one of those attributes, it is unlikely that a user will have a different secure password for each site they frequent. Far more often, users will eschew proper security practices in favor of the convenience of a password they already use frequently. It is crucial that password security is done right on the server side so as to help prevent human habits like common password reuse from becoming a bigger problem than it already is.

We had all of this in mind when we began working on one of our new products, Call Box. We recently had to decide on the best way to allow our first users to change their passwords, with the primary goal being that we wanted to ensure that each password change request is valid before allowing a change. As such, we opted to design a link users can click that sends them an email with a password reset link – the link remains valid only for a limited time before expiring and contains a randomly generated 25 character token string that we tie to the user. We require a certain level of complexity for any password coming in, and ensure that passwords entered into our system are properly encrypted so that the only person who truly knows their password is the person who made it.

These safety features are meant to help keep our users secure, but just as you must wear your seat belt properly in your car for it to be any use in an accident, these measures can only help if users are mindful about how they are adhered. Reducing password reuse and making your password harder to crack are two excellent steps towards ensuring that your passwords are secure, and thus that your privacy is maintained. If a mindful user is paired with secure technology, both will be far more secure that either could be alone.

Power to the user

Last week, we released a new feature that allows users to create advance routing profiles for tracking lines. We offer four types of advance routing profiles for our clients: scheduling, round-robin, bridge and multi-ring. While advance tracking line routing isn’t ground breaking in the call tracking industry or new to CI, the ability for users to create their own advance routing profile is a huge step forward for us. Previously, every advance routing request has to be set up by the CI support team. For example, if a client wants to set up a bridge, they would have to send a message to support and they will set it up for them. The process is lengthy and takes many valuable support team hours to complete. When we decided to revamp our tracking line portal back in October, advance routing profile was on the top of the list in terms of features we wanted to add. The ability for users to create their own advance routing benefits both our clients and our support team. The client will now be able to manage their own routing instead of needing to message support for every little change. This feature will also free up support, giving them back time to focus on other errors that have bigger impacts on the system.

MANDNIS

Although we had the idea for a while, the project itself took a while to build. The routing profile was the last part of many changes we were making. Before we created the new routing profiles, we had to make some changes to our database to support the new profiles. We also have to put a lot of thought into how our users will use the profile. When designing the profile, it’s important to think about all the worst case scenarios where our user can use our tool incorrectly. By building for the worst case, we cover all the possibilities where the profile editor can fail. During the coding process, a single page often requires days of testing before we can mark it as completed. One of the biggest problems we ran into was tracking line update speed. When someone updates their profile, it will take some times for the update to reach the phone system from our server. Initially, it was taking hours to update the phone system to match the profile updates. However, after weeks of testing, we managed to trim the update time down to minutes. In the end, we created a user friendly tool that will save both us and our clients valuable work hours.

If you haven’t seen the new routing profile yet, head over to the routing profile page and take a look.

Life is big, don’t overlook the small things

As fast pace and exciting the life of coding is, there are times where the rut sets itself in; the worst part is that you never know how bad it’ll be this time. Alright, I want you to close your eyes and imagine this,(Don’t actually close your eyes, you need those to read) you’re running a maze, it’s super complicated but you’re way ahead of everything. You’re jumping when you need to jump, turning all the right turns and you finally get to the end. There it is, the finish line, you cross it but no lights go off, no gun shots, no applause; just you and the crickets. What happened? Why didn’t you win? You’re then told that you have to cross the finish line with a specific red towel hanging from your waist in order to win; But there are hundreds of towels in the maze. You are then told to go find it and bring it back.

This is like trying to debug some code that you’ve written. You finish everything and you’re feeling on top of the world, you then test it and your world crumbles down fast. Then you’re stuck with this giant, intimidating chunk of code that only you understand best; and you have to find a way to fix it.

Of course you’re going to go back and look for the big things, they’re just the easiest to spot. It’s almost never the big chunks, it’s surprising how often it’s something really small. I’ll give you an example. But the worst part is that the following really happened.

So, as you may already know, I’m a developer for Century Interactive; but I started as a call reviewer in the Humanatic section. This is relevant because in order to become a developer I had to learn to read, write and think code; Of which I had a very minimal amount of (Not remembered) experience from one semester. So I started learning on a great coding training website called codecademy.com. I learned quite a bit but things got really tough when Javascript found it’s way into my life, I remembered very little from that one semester but just enough to know that Javascript is what we were (supposed to be) learning.

So I was working on getting one of the lessons done for my training and I got to the end of it, it wasn’t easy but I did it. I made my final changes and clicked submit; It turned red and said I couldn’t move on until my code was fixed. So I sat back, looked at my screen, and flipped the table. Wait, sorry, that’s what I wanted to do. What I actually did is sit back, look at the screen and scan some of the code. Right off the bat, I don’t see anything so I look a little closer; I find nothing. I continue looking for about an hour, looking things up on Google, taking the hints, and the walk-throughs, everything; Nothing worked. So, it’s about the end of the day now and I go home for the night with the thought of what I’m going to do with that code when I get back to work.

I’m back in the office, sitting at that desk, having a good ol’ fashion staring contest with my computer. I lean over to my buddy Cameron and ask him to take a look(He’s going through the same training). We both look at it for a good 30 minutes, then he gives up so I go back to looking at it alone. I ask him what he thinks I should do and he tells me to ask the CEO of our company who has a lot of coding experience.

So I go up to the CEO and ask if he could help me with something. We walk back over to my desk and I explain the issue. He looks into it for about 10 or 15 minutes and says he doesn’t know, we both laugh and he walks back to his desk.

At this point I feel helpless. I’m frustrated, I swear I’ve grown a white beard down to my chest in the past two days. I just don’t know what to do. I’m staring at all the code, lost. But then, I come across something, something tiny, something so small I wanted to walk out that very day.

Turns out, I’d forgotten to put a semicolon at the end of ONE line of code. I’d been looking for everything except that. So if you take one thing from this, let it be to not overlook the small things.

Coding is fun

Responsive Development: discovering new user scenarios

Recent technology advancements have opened new possibilities for responsive web applications that are at the forefront of changing the way we think about designing a new product. We can maximize impact at all screen sizes because we are not limited to a design that is a compromise between all possible use cases. Usually this means keeping things flexible from a technical standpoint and design that is fluid and meant to change. This flexibility can start to translate into infinite possibilities.
At its simplest level, making a web application responsive means making sure that the design looks as good on a mobile device as it does on a desktop computer. When we design responsive websites we consider how it will be used to help decide which features should be eliminated to fit into the available space, which are altered to better fit the user’s needs, and eventually what we need to add. Sometimes it means simplified design trends such as flat design, which adapts easily to all device sizes and is starting to break free of the restraints of pixel-based graphics. At the same time it enables design with extra bells and whistles like full-screen, high resolution graphics and videos that can be removed for slower device connections.
As we continue to make improvements to these applications we think about maximizing the potential benefit we can offer the user. We may start to realize that the user is more interested in using this application while on the go than while sitting at a desk. Suddenly the users are no longer sitting at a desk, but maximizing their time while waiting for an appointment or checking on critical data while in transit. Maybe they even want to use the site on mobile and desktop at the same time. What starts with adapting a design to look good on all devices leads us on the path to developing products that evolve to help us discover new use cases.

Do what you do best: Computers vs. Humans

Meet the Turing Machine, the world’s simplest computer. It consists of an infinite strip of paper separated into cells, a motor for moving between those cells, and a device for changing the information on each cell, or just checking what is currently recorded and using that as an instruction. Also, each cell only contains either 1 or 0, also known as a binary value. This machine, despite being so simplistic, can simulate any computer algorithm ever created.

Of course, this machine is mostly just theoretical. There isn’t much applicable use for making such a machine, and only a madman would attempt to write programs on such a device. But it illustrates a very important aspect about programming.

Computers can complete simple operations quickly, efficiently, and accurately, much faster than a human can. In fact, one of the most computationally wasteful times for a computer is when waiting for input from a human, because it wastes so many cycles just sitting there while you press each key to give it the necessary information to proceed.

This fundamental idea of rapid execution of simple instructions is crucial. If we can automate a process so just the computer can handle it without any human interaction, then the process can be done much faster. This is usually easier said than done, as we humans rarely think about all the minute steps we do to accomplish something we consider simple like going for a walk or having a conversation. But once we have established an automated process, a computer can perform it much faster than a human.

This is why things like Car Wars reports are so useful. You could manually document everything about your phone calls, organize it, compare averages, calculate percentages, draw up graphs, and finally obtain a report that displays your current status in a useful format, but that is a lot of work for humans that doesn’t require a lot of problem solving or critical thinking; it could easily be broken down into a series of steps.

We have a large variety of automated processes happening behind the scenes doing just that to manage the information into these reports. Anytime a user clicks on a report, computers are filtering through data to find what they need, performing operations on it to get things like percentages or max values, organizing it into easy to read formats such as graphs or pie charts, and then displaying the information in an interactive format that allows the user to look through the information and further request changes to display or the information filtered.

This gives the human data in a format that is easy to understand, allowing the identification for trends in activity or problem areas that need to be addressed. And at the same time, it gives the computers a very clear job with definite instructions, which it can use to accomplish this task efficiently in a timely manner. This is the power of computing; having a computer do what it does best, which is fast calculations, while a human does what they do best, which is making decisions and problem solving.

How to Stay in the Loop!

Here at Century Interactive we pride ourselves in the fact that we can not only build some of the best solutions for businesses, but also in the fact that we ship products at an unmatched rate compared to our competitors and other technology companies. Sometimes we move so fast that we forget to let all our customers know of the great reports and tools that we have built to help their business “Own The Phone!”

Over the last couple months we have taken an extra effort to let our customers know about all the neat and excited things that we’ve built by way of “Product Announcements” and “Lead Box alerts.”

You may have seen them before but if not I’ll give you a brief overview of each:

Product Announcements:

When we make a significant change or upgrade to the platform we want you all to know! By utilizing these Product Announcements upon logging in you will be welcomed with something like this:

announcement

We have a great group of developers that love challenges and creating simple solutions to your big problems, with Product Announcements we will ensure that you are in the know when we make a huge additions to the platform, so next time you see an Announcement check it out and see how we are making your day to day better!

Lead Box Alerts:

LBA

These alerts are more specific and catered to your product, account, and users. You should be actively utilizing your Lead Box already so by sending you and your business these Lead Box alerts you can stay on the most important page in the platform all while being updated on activity going on in your account.

As we continue to build we want to not only brag about the what we built, but we want you to utilize so that you can take full advantage of the product and get more value than you would’ve ever expected.

Be on the look out for more spectacular things to come!

Delight: An Unnecessary Necessity

At the top of Aaron Walter’s pyramid of the user’s needs sits delight.

So what is delight in software? I like to think of delight as an unnecessary positive addition to the experience. This can be anything from a hover effect to a video or even clever text. Elements of delight do not contribute to the functionality, reliability or usability of the product; they are purely for fun. Let me show you a couple examples.

A common form of delight is what most people call Easter Eggs. These are fun, surprising features of a product. A popular example is Google’s Do a Barrel Roll. If you type ‘do a barrel roll’ into Google, the window ‘does a barrel roll’ and your screen flips around in a circle.

Delight does not always have to be as wild as doing barrel rolls. They can be as simple as a picture or drawing. Google’s 404 page is a good example. Reaching a 404 page is never fun, but Google makes it a little less painful with a cute, broken robot.

My favorite example of delight is Hipmunk’s flying chipmunk. While this site is searching for your flights, the cutest chipmunk on the internet bobs back and forth like he is flying. It’s adorable.

So why do I think these elements of delight are necessary? Because they give the user something to remember. They bring emotion to a process that is so automated. Searching for flights is terrible! I usually leave the experience feeling like I just wasted an hour staring at a screen full of high prices instead of feeling excited for my upcoming trip. Hipmunk is fantastic because it is very easy to use, reliable and functional, but without that chipmunk I probably would not use Hipmunk as much as I do. It is not often I smile when I am searching for flights, but I smile every time I see that little guy.

Elements of delight can give a company a personality. They show the user that there are not only computers behind the product, but people. People design and build everything you use, but too often a product might as well have been designed by a robot. Displaying delight in a product brings out the human in our world of monotonous data gorging.