Sorry, I should have explained some of my reasoning a little better. The reason I used flags to identify the application type is that I was thinking that some applications might fall under more than one application class. If integers or strings are used, then it makes all the programs have to be aware of a whole range of values. For example, let's say that the number 2 indicates a view editor only, but the number 17 indicates a utility capable of editing views and editing picture resources. In that case, AGI Studio or whatever would have to look at the app. type integer like this:
if (apptype == 2 || apptype == 17, etc.)
{
caneditviews = true;
}
The version number isn't really used to determine the type of application. But if the first three bytes or so of each packet are the same, then the IPC standard can be changed later on down the line (for example, the header formats, except for those first three bytes, might be completely changed) without breaking existing apps. The existing apps would simply know, "hey, i can only handle version 1 packets" and be able to respond appropriately. Which I guess suggests that there ought to be a "version number too high" type of message, or maybe a general error message with maybe a 32-bit error code field.
on TCP, lengths, and splitting messages: yes, TCP does guarantee delivery of a packet or an error (in this case, since it's on the same machine, there's almost no chance of delivery failure unless one of the apps. screws up). However, TCP is a bytestream protocol with no record boundaries, so the length field is very helpful in determining how much data should be received into the current record. TCP might fragment messages over a network for some reason or another during routing, but I don't believe there's a theoretical limit on how large a packet can be. The only real purpose to splitting up the packets is so the length field can be valid. The packets could be made much larger if the length field counted, for example, how many 32-bit words there were in the packet. In that case, the packet could be 65535 * 4 = 262140 bytes each, but I don't really see where it would decrease the complexity any, so I didn't do things that way.
That focus message is a good idea. It would mean extra complexity in the utilities, though, because they'd have to be monitoring for focus messages and such while doing whatever other work they do. It would mean multi-threading almost for sure. I think Windows Sockets let you asynchronously monitor your app's TCP receive buffer, but I don't think other OS's do that without multi-threading (as the simplest route).
I think it's reasonable to allow multiple utilities to be opened at once by AGI Studio (that's one reason why there's a session id field). I think that would really be up to the designer of the program that's using the utility, though.
One difficulty I thought about is when the utility app sends its data back to AGI Studio. I guess it depends on what sort of editing AGI Studio expects the utility to do. Something like the BLG should create source code, send it back to AGI Studio, and then close. But if somebody developed their own AGI syntax-highlighting editor, then that would be a source code generator application that needs to be able to be left open, possibly even to have access to a compiler through the IDE. It wouldn't want to close just for sending data back to AGI Studio. What if the user has been writing for a long time and just feels it's necessary to save? They wouldn't want the logic editor closing on them in that case. But AGI Studio does need to accept and save the data.
Anyway, I'll stop for now before this turns into an essay.