A Whoops Moment with Erlang

I”ll building my first non-trivial Erlang application, a server using the gen_tcp library, and I was left scratching my head for awhile with a problem today.  When I tried to connect to the server and send data with a really simple Python script, no data was being received by the server.  The incoming connection was handled by accept/1 properly, and the Python script didn’t seem to be reporting any errors.

I have to admit that I know next to nothing of Python, and I still consider myself a beginner in Erlang, so I was a bit concerned.  I wasn’t quit sure where the problem was being caused, so I switched the test client over to Erlang first.  I still could not receive any data at the server, so the problem seemed to be server-side.  Next I fired up the Erlang debugger to follow the execution of the server.  Sure enough, the server accepted the incoming connection and was blocking in the receive area.

The next step, which in hindsight I should have done first,  was to check all of the parameters to the listen/2.  Everything looked good, but I was unsure about the packet parameter and what it is used for.

 {backlog, MaxCon},
 {active, once}, 
 {packet, 2},
 {reuseaddr, true}

Why was packet set to 2 again?  The listen/2 man page doesn’t mention anything about this parameter, but the inet:setopts man page says the following:
Defines the type of packets to use for a socket. The following values are valid:

raw | 0
No packaging is done.
1 | 2 | 4
Packets consist of a header specifying the number of bytes in the packet, followed by that number of bytes. The length of header can be one, two, or four bytes; the order of the bytes is big-endian. Each send operation will generate the header, and the header will be stripped off on each receive operation. 

 What I did not realize, however, is that this parameter is not simply internal to Erlang.  If the client and the server don’t have the same settings, no data will flow between the two.  I changed the packet value to 0 in the server, and after rerunning the test client script, sure enough, data flowed from the client to the server.

I really felt like an idiot for missing this.