Changing TCP packet format

I have to deal with a TCP connection from other software where the format of a “packet” changes. It starts out as text delimited by newline characters but at a certain point needs to change to {packet,4} format, with a 4-byte count followed by binary data, so that I can pass the results of term_to_binary reliably.

But when I call inet:setopts( Socket, [{packet,4}] ) it returns einval. Where is this restriction coming from?

I can’t replicate it:

1> {ok, S} = gen_tcp:listen(10000, []).
{ok,#Port<0.4>}
2> inet:setopts(S, [{packet, 4}]).
ok

Can you provide more info about Socket and any other stuff that could be relevant?

The socket was created by gen_tcp:connect with options of [{active,true},{mode,binary},{packet,line}]. A few lines of ASCII text had been exchanged as part of the protocol and after that the connection becomes just a raw byte stream. Since I want to exchange arbitrary Erlang terms over this channel, the easiest encoding seemed to be term_to_binary and then prefix a 4 byte count. I know that I am responsible for adding and stripping the 4 byte header but I figured that setting {packet,4} format would save me the trouble of buffering chunks until I had met the specified length and lower layers would do that.

I still can’t replicate it:

1> {ok, S} = gen_tcp:listen(10000, []).
{ok,#Port<0.4>}
2> {ok, S2} = gen_tcp:connect(#{family=>inet, port=>10000, addr=>{127,0,0,1}}, [{active,true}, {mode, binary}, {packet, line}]).
{ok,#Port<0.5>}
3> gen_tcp:send(S2, <<"some ascii">>).
ok
4> inet:setopts(S2, [{packet, 4}]).
ok

What OTP version are you using? Can you provide minimal code sample that causes error?