Sockets

Summary

If you’ve ever used netstat, or gone to a website on OSX or Linux (or Windows for that matter) without a background in C (or perhaps systems programming), you may have struggled to fully appreciate the content there in. Or maybe you are just curious to know how sockets work in *nix.

sockets are a form of IPC, or inter process communication, allowing processes to bidirectionally share information with other processes. See other kinds of IPC in Beej’s Guide to Unix IPC.

sockets are commonly referred to by their Address Family, seen in constants such as AF_UNIX, or AF_LOCAL, representing local sockets specifically. You might also want to know about Protocol Family, seen in constants such as PF_UNIX and PF_LOCAL.

Valid socket types that should be known are:

typedescription
SOCK_STREAMA stream oriented packet used for TCP
SOCK_DGRAMdatagram oriented packet, no reordering, used for UDP
SOCK_RAWProvides access to internal network protocols and interfaces. Only available to super-user
SOCK_SEQPACKETA sequence-packet socket that is connection oriented, delivering messages in the order sent

You can learn more about various types of valid sockets on the man page for the socket SystemCall:

https://man7.org/linux/man-pages/man2/socket.2.html

Now that we’ve discussed what sockets are, and some of the well known constants that sockets use, let’s look at the example in the man page.

Unix Socket Example

The given snippet in the man page is a bit terse, but practical:

       #include <sys/socket.h>
       #include <sys/un.h>

       unix_socket = socket(AF_UNIX, type, 0);
       error = socketpair(AF_UNIX, type, 0, int *sv);

In the example above, we import the definitions for socket and unix domain sockets, then construct a unix_socket, and assign error the exit code of calling socketpair.

It is helpful to consult the manual, let’s take a look at the two syscall signatures from their respective man pages:

int socket(int domain, int type, int protocol);
int socketpair(int domain, int type, int protocol, int sv[2]);

Using what we’ve learned about valid types, we can construct a simple program that creates a socket, and prints its file descriptors or any relevant error:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>

int
main()
{
    int unix_socket, error;
    // socket vector, sv, is a vector pointer to two file descriptors
    // representing new sockets for server and client bindings
    int *sv[2];

    unix_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
    // socketpair below is constructed for the OSX variant. The linux variant has a different signature, instead use:
    // error = socketpair(AF_UNIX, 0, *sv)
    error = socketpair(AF_UNIX, SOCK_DGRAM, 0, *sv);

    if (error != 0)
    {
      printf("Encountered error: %d\n", error);
      return error;
    }

    printf("Socket descriptor: %d\n", unix_socket);
}

Compiling and running our example can be done by running:

clang -o socket ./socket.c; ./socket

Socket descriptor: 3

Ok, so we created a socket, and it returned a descriptor, 3. What does that mean?

You are likely familiar with file descriptors 0, 1, 2 if you’ve ever redirected output. They are stdin, stdout, and stderr.

References

  1. Beej’s Guide to Unix IPC
  2. unix-7 man page
  3. socket-2 man page
  4. unix domain socket wikipedia
  5. What’s the difference between Unix sockets and TCP/IP sockets
  6. File Descriptors

Hugo

This site is powered by hugo. I love the simplicity of writing markdown, pushing it to this repo, and having that transpiled into HTML through a github action. There are a lot of tools in this space, such as the popular Sphinx, Mkdocs, and Jekyll.

I chose hugo specifically for how little setup was needed for a self publishing repo to manage my site on Github Pages. Using this service, the project’s url becomes <YOUR USERNAME>.github.io, or <YOUR USERNAME>.github.io/<YOUR PROJECT>/, and supports custom domains.

For more information, see:

To get started, create the repo, and brew install hugo if it’s not already available.

NOTE: name this repo <YOUR USERNAME>.github.io for your personal username repo, otherwise if you’re bringing your own repo, you can use whatever name you want

Initializing the project

Hugo will scaffold out your site for:

hugo new site hartje.io
cd hartje.io

Next, find a theme you like, then click the Download button find it’s git repo. You now need to add it as a git submodule, and then init the submodule so it’s tracked in your source code. That might practically look like this:

git submodule add https://github.com/Wtoll/venture.git themes/venture --depth=1
git submodule update --init --recursive # needed when you reclone your repo (submodules may not get cloned automatically)

Configuring Hugo

Hugo has a lot of configuration options. You can configure hugo by creating a ./config.toml file, or even in whichever format you prefer out of yaml, toml, and json.

Setup Github Pages in your repo settings

By default, the GitHub action pushes the generated content to the gh-pages branch. This means GitHub has to serve your gh-pages branch as a GitHub Pages branch. You can change this setting by going to Settings > GitHub Pages, and change the source branch to gh-pages.

Source: Hugo - Hosting on Github

Custom Domains

If you’re bringing your own DNS, be sure to add your domain to /static/CNAME, as a requirement for Github Pages.

echo "hartje.io" > static/CNAME

/static/CNAME:

hartje.io

Create a post

hugo also has a scaffold for posts. To create a new post run:

hugo new mypost.md
# or alternatively, you can nest your posts in directories
# hugo new mydir/mypost.md

The created markdown files will be in the content/ folder.

Automatically publish changes to Github Pages

We can make quick work of an automated deployment for our site, by adopting this simple github workflow. Add this .github/workflows/gh-pages.yaml and push your branch to set it up.

/.github/workflows/gh-pages.yaml:

name: github pages

on:
  push:
    branches:
      - main  # Set a branch to deploy
  pull_request:

jobs:
  deploy:
    runs-on: ubuntu-20.04
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true  # Fetch Hugo themes (true OR recursive)
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: 'latest'
          # extended: true

      - name: Build
        run: hugo --minify

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        if: github.ref == 'refs/heads/main'
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./public

Customizing Hugo

First, here is a wonderful tutorial for adding custom css or javascript to your hugo site from banjocode.

If you’d like to customize your hugo site layout, then first take a look at the structure of our theme:

tree themes/venture
themes/venture
├── LICENSE
├── README.md
├── archetypes
│   └── default.md
├── assets
│   └── sass
│       └── main.sass
├── images
│   ├── screenshot.png
│   └── tn.png
├── layouts
│   ├── 404.html
│   ├── _default
│   │   ├── baseof.html
│   │   ├── list.html
│   │   └── single.html
│   ├── about
│   │   └── list.html
│   ├── index.html
│   └── partials
│       ├── footer.html
│       ├── head.html
│       └── header.html
├── static
│   └── images
│       └── blank.png
└── theme.toml

You might recognize that the theme repo’s structure matches the one scaffolded by hugo. hugo will prefer a root level file, should the theme have a conflicting file, so we can explore what all we can change and experiment by copying to the root level and modifying it.

For instance, if we wanted to update the layouts/partials/footer.html, we’d want to first copy the theme’s into our root level layouts/partials, then modify the file in /layouts/partials/footer.html.

mkdir -p layouts/partials
cp themes/venture/layouts/partials/footer.html layouts/partials/footer.html

About

it me

apiVersion: human/v1
kind: Nerd
metadata:
  name: Ryan Hartje
  namespace: Austin, TX
  labels:
    pronouns: "he/him"
    occupation: "software engineer"
    hobbies: "running, biking, horsing around"
spec:
  social:
    github: https://github.com/goshlanuage
    linkedin: https://www.linkedin.com/in/ryan-hartje/
    twitter: https://twitter.com/xoxodeadbeef