You have a bug in your code. The moment you do List.ToArray(), it creates a new array object. So, the socket is putting data into this new array, and not in the original List that you have.
We could help better if we understood exactly what the messages are, and what their formats are? If you have control over your device, you could have it send each message preceded by an integer which tells how many bytes are coming in data. Then you could issue a read for exactly that many data bytes...
// allocate a data buffer for some max length.
byte [] buffer = new byte[1024];
// issue a read for 4 bytes, which is the header that signifies
// the length of data coming later.
int read = Socket.Receive(buffer, 0, 4);
int dataSize = BitConverter.GetInt(buffer, 0, 4);
// now issue a read for dataSize #of bytes
read = Socket.Receive(buffer, 0, dataSize);
I havent tried this code snippet, but I think you could get this to work. And you could add more metadata about the packet after the header, for eg, add the CRC etc.
On my blog, I wrote a series of articles on how to implement PING with Sockets. In that you could get some idea on how to structure your packets.
http://ferozedaud.blogspot.com/2009/09/implementing-traceroute-with-systemnet.html
Hope this helps. Good luck!