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
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
Dial seems to be a lower level implementation, it just uses a switch case internally and invokes
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:
- DialTCP calls dialTCP
- dialTCP calls internetSocket which returns a socket
- newTCPConn binds the socket to give a net.TCPConn
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.
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.Writer. conn implements a the
Conn interface. If you look into
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 :)
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.
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.
- TCP connection needs a TCP socket which is gotten by using
- Go uses
writesyscalls to read and write from the socket
- Implement a simple TCP Client.
- Try to do it using the
recvsyscalls as mentioned in the above networking post.