Skip to main content

Ethan Thornberg

Week 1: Proving I Can Stick With Hard Things

Ethan Thornberg14 min read
Deep WorkNetworkingLearningTCPDiscipline

Week 1: Proving I Can Stick With Hard Things

I have a 3.95 GPA at UC Irvine as a Regents Scholar. On paper, it's a success. To me, it's a warning sign.

I'm a professional beginner.

I've spent my life acing things by skimming the surface, relying on quick intuition to get through exams without ever sitting with a problem long enough for it to hurt. I understand concepts quickly. I ace exams without studying much. I've never had to put in hours of focused work to succeed academically.

I get interested in something - game development, machine learning, web frameworks. I dive in excited. Learn the basics fast. Build a small project, feel accomplished, and then... it gets boring. Or hard. Or both.

So I switch. New interest, new project, new excitement. Repeat.

I've been doing this for years. I've never mastered anything. I'm decent at a lot of things, but I've never gone deep enough to become genuinely expert.

Working at First American as a software engineer, I see what real expertise looks like. Engineers who've spent years going deep on specific problems. Who understand systems from the ground up. Who can architect solutions because they know the fundamentals cold.

That's not me. Not yet. Maybe not ever, if I can't break this pattern.

I'm terrified that if I don't learn how to be bored, I'll spend my whole career being "pretty good" at everything and an expert at nothing.

Knowing I had potential but never proving it - that terrifies me more than failure ever could.

The Experiment

I'm spending six months learning real-time networked systems from scratch. Not for a class. Not because I'm passionate about it. Because I need to prove I can stick with difficult work when the initial excitement fades and boredom sets in.

This isn't about networking. It's about whether I can sit with difficulty long enough to change who I am.

Cal Newport's books gave me permission to stop waiting for passion. You don't need to feel motivated. You need to become so good they can't ignore you.

Get good first. The passion follows.

That reframe unlocked something. The boredom I keep running from? That's not a sign I'm on the wrong path. That's where everyone who masters something has to push through.

The Plan

Six months felt right. Short enough to see the end, long enough to hit real boredom and roadblocks.

Real-time networking was the topic. It's practical - I'm interning at Roblox this summer working on multiplayer systems. It's interesting in theory - I've gamed my whole life. But I'm not emotionally passionate about TCP sockets and protocol design. I knew it would be useful. I understood its value. But I wasn't naturally motivated to work on it for hours.

That was the point. If I could stick with networking through the boring parts, I could stick with anything.

I asked Claude AI to help outline topics by month (networking fundamentals, state synchronization, client prediction) but I didn't overthink it. I always get caught up creating the perfect plan instead of starting. This time I just started.

The Rules

2:00pm to 4:30pm, every weekday, at the Starbucks across from campus.

I don't go there for the caffeine (though the occasional latte doesn't hurt). I go there for the social pressure. There's a specific kind of accountability that comes from being a guy with a laptop in public. I'm much less likely to impulsively check Instagram or fall down a YouTube rabbit hole when I feel the (likely imaginary) gaze of strangers. My phone isn't just on silent. It's face down and out of reach.

Classes end by 2pm, so this time is always free. Having the same slot every day removes the decision.

If I hit a wall and can't focus, I'm allowed to sit there and stare at the wall for twenty minutes. But I am not allowed to escape.

Success isn't how much I learn. It's whether I showed up for 2.5 hours and kept attention on the work.

Week 1: Building From Zero

Days 1-2: The Foundation

I read Beej's Guide to Network Programming cover to cover for the fundamentals. What sockets are. TCP vs UDP. The data structures. IPv4 vs IPv6.

Pure information digestion for 5 hours across two days.

I ordered the book in physical form. Having something tangible helped me with focus. I took extensive notes, which is pretty unusual for me. The data structures made no sense at first - all abstract until I could see them in actual code.

Days 1-2 were easy. New project energy. Excited, completely focused, motivated.

I didn't know it yet, but this was motivation, not discipline.

Day 3 - Wednesday: It Works

First working client and server. Copied line by line from Beej's example. Typed every line myself.

Not copy-pasting. Typing. The friction of typing forces understanding. You read each line, notice patterns, hit errors, and figure out why.

The code was basic. Create a connection point, bind it to a port, listen for connections, accept one client, send a message. Maybe 100 lines total. It was the first time seeing Days 1-2 concepts actually work together.

Then I compiled it. It worked.

I ran the server in one terminal. It printed "waiting for connections…" and the cursor sat there, waiting.

I ran the client in another terminal.

The server updated: "Connected to Client on Port 9034"

The client showed: "received: Hello, world!"

Two programs talking to each other. That's not abstract anymore.

Then came the real work. Understanding what I'd just typed.

I went back through the code line by line, adding comments explaining what each part did and why. Not just what - the why. Why bind() before listen()? Why does accept() return a new connection? Why getaddrinfo() instead of hardcoding?

This took longer than typing the code. An hour just on comments and lookups. But this is where the learning happened.

About 45 minutes in, I wanted to quit. It felt endless. I'd type an explanation, realize I didn't understand it well enough, go back to the book, read more, try again.

The voice in my head said, "You got it working, that's enough. Figure out details later."

But I knew that pattern. Getting it working isn't enough. "Later" never comes.

I reminded myself that there's no timeline. I don't have to finish in one day. I just have to keep trying to understand instead of moving on.

By the end of the session, I had a working client-server program with detailed comments explaining most of it. Still fuzzy parts, but way more understanding than when I started.

Day 4 - Thursday: The Wall

This was the day the experiment started.

I typed Beej's multi-client server with poll() line by line. This took forever.

I started at 2pm. By 3:30pm I was still typing server code. Line after line of C code I didn't understand yet.

Day 3's server was maybe 100 lines. This one? Over 400 lines. Functions to create, data structures to manage, arrays to track multiple clients, and logic for adding and removing connections.

Thursday was the first day the "new project energy" died.

I was just copying it, trying to understand as I went, but mostly... typing. It was less like engineering, more like being a human copy machine.

It was the first day I struggled to stay focused. My mind kept wandering. "Why am I typing all this? I could just download the example." "This is taking too long." "I'm not even learning."

The boredom was physical. A restless itch to click away, to find a hit of dopamine anywhere else.

Complexity jumped dramatically. Day 3 was linear - do this, then this. Day 4 introduced poll(), which works completely differently.

Instead of blocking on one connection at a time, you maintain an array of all connections you're monitoring. Call poll() which blocks until ANY has activity. Loop through to see which are ready. Handle new connections differently from existing messages. Remove disconnected clients.

Each piece made sense in isolation. Putting it together was overwhelming. Arrays of structures I'd never seen. Pointer manipulation. Managing indices carefully.

And it was repetitive. Type a function definition. Type implementation. Type error checking. Type another function. Repeat.

I hit a wall at 3:15pm. Usually, this is where I'd quit.

Instead, I walked out to the patio and sat for ten minutes. Nothing. No phone, no music, no "productive" thoughts. Just let my brain reset.

When I went back inside, the code was still boring, but no longer overwhelming.

Mastery isn't being "on" for 2.5 hours. It's returning to the desk after the tenth time you wanted to leave.

I finished typing both files by 4:15pm. Then the review phase.

I went through the entire server line by line. What is this doing? Why is it necessary? What would break if I removed it?

When I couldn't answer, I marked it to look up later and kept researching.

The "aha" moment about poll() came around 4:20pm - ten minutes before my session ended. I'd been thinking of it as "checking which connections have data." That's incomplete.

poll() exists to prevent the server from getting stuck on any single client. Without it, one slow client hangs the entire server while everyone else sits there unable to connect or send messages.

With poll(), the server watches all connections at once. When any is ready, it handles that one. No wasted cycles. No blocking. This is how real servers handle hundreds or thousands of connections without creating a thread per connection.

The code I'd been typing for 2+ hours suddenly made sense as a cohesive system, not just syntax.

While typing: 50% understanding. After reviewing: 95%.

By the end I compiled the multi-client server. Ran it. Connected with telnet from multiple terminals. Watched them communicate. It worked.

More importantly, I understood why.

Day 5 - Friday: Writing From Memory

Friday. Four days straight. I was visiting my hometown for the day, rare for me. Dedicating 2.5 hours to this when I only had the day felt strange. I made an exception to my time slot but not to the commitment. Different location, same 2.5 hours.

Sitting at a cafe at 12pm trying to write network code from memory.

Zero motivation. Zero excitement. Just obligation.

The goal was to write a client that connects to my multi-client server and sends messages. From scratch. No looking at my Day 3 client code.

I could use official documentation (man pages, Beej's Guide for function signatures), reference materials, my own notes. I couldn't use existing client code to copy from, AI to generate it, or tutorials.

Started with the skeleton in my head. Create socket, connect to server, send message, receive response, close. Then filled in each section.

Every single line required active thinking. What comes next? What does this function need? What structure am I working with?

Slow.

Around 12:45pm, 45 minutes in, maybe 50 lines of code. Syntax kept having errors. Forgot semicolons. Mixed up pointer syntax. Typed wrong structure names.

Each compilation showed new errors. Missing includes. Wrong arguments. Type mismatches.

Normally I'd give up here. Or ask AI to fix it.

But that defeats the point.

So I did it the hard way. Read the error message. Find the line. Look at documentation to see what it expects. Fix it. Compile again. Next error.

Around 1:15pm, I hit a wall. The code was compiling but crashing when it would run. I couldn't immediately see why.

Again, that voice in my head said, "This is taking forever. You're not making progress. Just ask AI."

I sat with that urge for about 5 minutes. Just sat. Stared at the code. Didn't try to force a solution, didn't escape. Just sat.

Then added debug statements to see where it crashed. Narrowed it down. Found the bug - I wasn't checking if a function succeeded before using its results. Added the check. Compiled. Ran.

It worked.

Client connected. Sent "Hello from client!" Received response. Clean disconnect.

Not triumphant. Not exciting. Tired satisfied.

Built something from understanding, not copying. Still had to look up syntax constantly, still needed references for function signatures. But the structure, the flow, the logic - that came from my head.

I still had time. Added a welcome message to the server for new clients. Then added sender ID prepending to broadcast messages. When one client sends "hello", others receive "Client 3: hello"

These modifications required understanding the server code well enough to find the right place to add features. Took another 20 minutes, got them working.

The gap between "I understand this" and "I can do this" is real.

That's okay. That's what experience builds. I'm not trying to memorize syntax. I'm trying to build understanding I can apply.

Day 1 felt like any other project I've started. Excited. Motivated.

Day 5 felt like work. Real work. Not fun, not exciting. Just necessary.

But I did it anyway.

I showed up on Day 5 when I'd rather be anywhere else. Stayed focused for 2.5 hours. Built something from understanding, not copying.

That didn't feel good in the moment. In the moment it felt hard and tedious.

Packing up my laptop, walking out of the cafe - that felt good in a quiet way.

I did the thing I said I'd do when I didn't want to.

What I Proved

By Day 3, the abstract "magic" of networking started to feel like architecture.

The server is like an apartment building - it has to have a fixed, known address so clients can find it. The client doesn't need a fixed address. Just needs to know where the building is.

When they "knock" (connect), the building manager (the server) doesn't just let them stand in the lobby. They hand off that connection to a specific "room" (a new file descriptor) so the lobby stays clear for the next person.

Suddenly, the 100 lines I'd typed weren't just syntax. They were a system for handling a crowd.

That one analogy unlocked the whole socket, bind, listen, accept sequence. Not memorizing steps anymore, getting why each exists.

poll() on Day 4 was harder. It took hours before I understood it's not about "checking connections" but about "not getting stuck on one client." It still feels somewhat magical how one function call can monitor hundreds of connections.

Now, I can build programs where servers and clients communicate. Make a chat server for local connections.

I can't communicate across different networks. Handle all error cases. Manage messages longer than a fixed buffer.

What's still fuzzy: how does a single file descriptor number enable communication between programs? I know the OS uses it to identify connections, but the actual mechanics are unclear. I also don't fully get when to use different structure types. Week 2 problem.

The technical learning is fine. The real work was showing up.

Day 1 runs on motivation. Day 5 runs on discipline. I showed up on Day 5. That's the win.

Time blocking helped the most. Having the same slot every day removes decisions. Phone completely away. Starbucks environment created accountability through social pressure. The 5-minute rule - sit for 5 minutes doing nothing, then go back.

I showed up all 5 days. Stayed focused. Pushed through difficulty. Understood (not just typed) what I worked on.

What I proved isn't about networking. It's about me.

I can show up for 2.5 hours every day, even when unmotivated and uninterested, and dedicate myself to learning something difficult.

Five days isn't long. It's nothing. But it's five days more than I've managed before on something boring.

What's Next

Week 2: UDP protocol. Connectionless communication. Build UDP client and server similar to what I just did.

End of Month 1 goal: fully understand how to send data to multiple clients in both UDP and TCP. Understand the pros and cons of different approaches.

The 5-month question: can I keep this up?

I'm most worried about getting lazy. Convincing myself I don't need this. Losing sight of the value.

I'm most excited about creating custom programs on my own with a full understanding.


This isn't a networking tutorial. There are thousands of those.

This is documentation of someone who has struggled with discipline his whole life finally proving he can stick with hard things.

I've bounced between interests my whole life, never mastering anything. This is me proving I can go deep.

Not advice. Real struggles and real wins.

Week 2 starts Monday. 2pm. Starbucks.

I'll be there - whether I feel like it or not.