Using tcpdump

I use tcpdump infrequently enough that I don’t have the arguments memorized, but frequently enough that I don’t like digging through the manual to find all the arguments I want. I originally posted this on my old employer’s community portal, but I find myself referring back to it enough that I thought I should copy it here.

Using tcpdump to capture packets on a Linux system

Sometimes when trying to debug a problem with a network application, it’s helpful to sniff the connection between the client and the server to get a better idea of what’s going on and which component is to blame. If you’re using a graphical environment, Wireshark (formerly Ethereal) makes it easy to capture and analyze packets, but if the server is a “headless” Linux machine, it’s not as straightforward. In this situation, I’ve used the tcpdump utility to capture packets on the server to a file, then transferred the file to my computer for analyzing with Wireshark.

The following command will capture all packets on the eth0 network interface and log them to a file called packets.tcpdump.

tcpdump -i eth0 -s 0 -U -w packets.tcpdump

tcpdump will continue to run in the foreground while you generate the network activity. When you’re done, press CTRL+C to stop tcpdump. Note that running tcpdump in this manner could have an adverse effect on network performance, so you should not leave this running in a production environment.

Capturing all packets also has a potential to use a lot of disk space if your network is busy. If you’re having trouble finding the traffic you want because the dump is too large, consider passing additional arguments to tcpdump to filter the types of packets that are captured, e.g., only packets from a certain IP address or only packets on a certain port.

The following command will only capture TCP packets destined for or originating from port 80.

tcpdump -i eth0 -s 0 -U -w port-80-packets.tcpdump tcp port 80

Of course, the downside to filtering the dump at capture-time is that you may miss something that helps you debug the problem you’re encountering. If you can afford the disk space and your network is not that busy, it may be better to capture all packets and just use a view filter in Wireshark to help you find what you’re looking for.

isset() vs. array_key_exists()

For most of my PHP career, I’ve used isset() to determine if an array has a certain key.

$foo = array();
echo isset($foo['bar']) ? 'set' : 'not set'; // Prints: not set

isset() is nice because you can also use it on regular variables and object properties.

unset($foo);
echo isset($foo) ? 'set' : 'not set'; // Prints: not set

$foo = new StdClass();
echo isset($foo->bar) ? 'set' : 'not set'; // Prints: not set

Somewhere along the way I learned that there was an array_key_exists() function, but by that time typing isset() was already muscle memory. I never bothered with array_key_exists() until recently when I ran across a situation where I actually needed it. I wanted to build a REST service with the following PUT (edit/update) behavior:

  • If you include a key and set it to a value, the key is updated with the value.
  • If you include a key and set it to null, the key is updated and its value is set to null.
  • If you PUT some JSON and you omit a key, that key is ignored and no update is made to that key.

The first two points are pretty obvious, but the third one is not. You could argue that this behavior isn’t very RESTful, but it prevents sending chunks of redundant data over a mobile link.

Anyway, back to isset() and array_key_exists(). Despite its name, isset() actually checks to see if the argument is set and is not null. So if you have an array with a key whose value is null, calling isset() on that key will return false.

$foo = array(
  'bar' => null,
);

// Prints: "not set" because $foo['bar'] is null
echo isset($foo['bar']) ? 'set' : 'not set';

In my service, I couldn’t tell the difference between the second and third use cases — the client setting a key to null vs. omitting the key entirely. The solution was to use array_key_exists() which only checks to see if the array has the key.

$foo = array(
  'bar' => null,
);

// Prints: "exists" because $foo['bar'] exists, even if it is null
echo array_key_exists('bar', $foo) ? 'exists' : 'does not exist';

Performance Considerations

I came across a blog post this morning talking about the performance of isset() vs. array_key_exists(). (That’s what reminded me to write this blog post, actually.) The takeaway is that isset() is actually faster than array_key_exists() because isset() is actually a language construct, not a function, so it doesn’t incur the function call overhead. But both are quite fast, so you probably shouldn’t choose one over the other for performance reasons.