However. It's all achieved on a wing and a prayer.
* When clients disconnect the server has no clue who it was and so the clients entity stays resident.
When you event_disconnect is called, before you run ent_remove, reference the skill upon which you have the client_ID and then use that to remove all client_ID's from everywhere.
* when running over internet, server crashes when more than 1 client joins
That is not normal. Your login routine is not stable yet. You are likely over-righting on the wrong array or net index when coming in causing the server to crash. You should be able to debug this with proficient use of the Diag() command and acklog_sv.txt file.
* I am still getting my head around where and when these functions are running
That's a good thing to get your head around, especially with MMOG. I recommend (if you haven't already) you look into UML diagramming and start diagramming your code. Trust me, it will seem like a waste of time at first, but in time, as the code grows and dependencies develop, it will be an invaluable tool in putting it all together.
* loads of un-needed stuff is being sent all the time
Again, with UML you can map out your network traffic. Make sure you are using the Dplay_ function to set your server and client clocks. As well, pay attention to the nosends (I like to do nosend_all myself). Finally, get a Packet Sniffer to read through the packets you are sending. This will help identify what is being put on the net and this will help you find where it's coming from.
* I am still not convinced I am getting unique pointers to clients, or am able to send exclusive strings
Let's not use the word "pointer" here shall we since it already has meaning in the engine. Instead, stick to "unique ID".

I'm surprised you are unable to send exclusive strings. This is something that A6 and A7 can do quite effortless. However, combining a unique client ID with sending strings can be confusing. In our case, we have a lookup table that converts our unique IDs into GS Handles. This way, whenever it comes time to put something on the network, we take the lookup the handle for a unique ID, use handle_to_pointer to get the pointer, and then use the pointer to send on. Convoluted but aside from the extra conversion step, quite easy.