Prologue

After attending GopherConIndia and talking to Brad, I wanted to contribute to the GoLang project (More on that later). And I chose this as my first issue to get used to the contribution process.

As I was diving through the net package source trying to document all the methods and functions exposed, I realized that I was slowly going one level deeper to the internal workings. I didn’t have a networking course until now, and I decided to understand networks by reading the source.

This is a completely new approach to learning stuff, read the source and Google a little to learn networks and I was pleasantly surprised. I could understand to fair degree how sockets worked and I am now confident that I can implement atleast the first four assignments in next sems Networking course :P

DialTCP

Yep. I am going to cover one function DialTCP and show how it uses a socket to compose the whole connection. The http package implements the HTTP protocol on top of the net package and huge shoutout to @bradfitz for his work. Below is a simple GET request to illustrate this.

I will be posting code via github gists through out this post and they are fully runnable samples. You can view the full file by clicking on the name of the file on the bottom left corner. We have an example function to send a GET request to http://google.com/ using DialTCP. The full gist also contains a slightly modified example using net.Dial. While Dial seems to be a lower level implementation, it just uses a switch case internally and invokes net.DialTCP

Some Basics

So, lets see how opening a connection works. As I said, I am no expert, but Google led me to this and he does it exceptionally well!

Now with that in mind, things get very simple. When we call net.DialTCP, these are the function calls that are made:

internetSocket

We now know that we need a network file-descriptor of type SOCK_STREAM to get a TCP connection. And thats what internetSocket does. It internally spawns a SOCK_STREAM. Now we will get a socket which is mapped to a struct netFd for manipulation. Next we intialise the socket by dialing, i.e, set the TCP addresses of the socket from its socketAddr.

newTCPConn

Now that we have a file-descriptor, we need to perform the Read and Write operations on it. We use a interface Conn which is a superset of the io.Reader and io.Writer. conn implements a the Conn interface. If you look into Read and Write methods, you will see that we are calling fd.Read which performs Read/Write syscalls to read and write. Go uses a networkPoller detailed here, which adds some complexity to the syscall but it can be safely ignored :)

Now while we have a generic conn, the TCPConn embeds conn and implements additional functions like SetKeepAlive. newTCPConn just takes the netFD and returns a new TCPConn.

Boom. Thats it. The length of the post seems to be small, but all of the content is inside the links which point to the source-code.

Epilogue

People said GoLang is easy to understand. Hell yes it is! And reading source code and blogging about it is a great way to learn. Expect more from me on this front.

Learnings:

  1. TCP connection needs a TCP socket which is gotten by using SOCK_STREAM
  2. Go uses read and write syscalls to read and write from the socket

TODO:

  1. Implement a simple TCP Client.
  2. Try to do it using the send and recv syscalls as mentioned in the above networking post.