I am finalspace and do programming since more than 25 years, started on C64 and got serious with borland delphi. Nowadays i use C/C++ only.
I am finalspace and do programming since more than 25 years, started on C64 and got serious with borland delphi. Nowadays i use C/C++ only.
mmozeiko
My main suggestion would be to NOT do simple wrapper around BSD sockets. Do a bit more. Create all API nonblocking/async. Most difficult part will be dns resolving. On Win32 it is built in, but on Linux you'll need to do more code (don't use GNU libc specific functions, so it is portable). Allow user to do sync requests by explicit wait function, and/or what ratchetfreak suggests - integrate with gui event loop. Don't do high level functions ("send object position"), allow to send/receive raw bytes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | // Does not do any byte-order conversion // Data wont be send in multiple packets. When it does not fit it will be cut of. size_t fplSocketReadRaw(const fplSocket *socket, const size_t size, uint8_t *targetBuffer); size_t fplSocketWriteRaw(const fplSocket *socket, const size_t size, const uint8_t *sourceBuffer); // Does not do any byte-order conversion // Bytes will be send/received in multiple packets if needed (Datagram limitation) // Appends a header automatically, so you dont have to deal with limitations size_t fplSocketReadBytes(const fplSocket *socket, const size_t size, uint8_t *targetBuffer); size_t fplSocketWriteBytes(const fplSocket *socket, const size_t size, const uint8_t *sourceBuffer); // Does byte-order conversion automatically int16_t fplSocketReadS16(const fplSocket *socket); int32_t fplSocketReadS32(const fplSocket *socket); // Does byte-order conversion automatically size_t fplSocketWriteS16(fplSocket *socket, const int16_t value); size_t fplSocketWriteS32(fplSocket *socket, const int16_t value); // Does byte-order conversion automatically size_t fplSocketWriteS16(fplSocket *socket, const int16_t value); size_t fplSocketWriteS32(fplSocket *socket, const int16_t value); // Does byte-order conversion automatically (Wide <-> UTF-8) // String will be send/received in multiple packets if needed (Datagram limitation) size_t fpSocketWriteString(fplSocket *socket, const char *source, const size_t sourceLen); size_t fplSocketReadString(fplSocket *socket, const char *maxTargetLen, char *target); // Resolving / Lookup bool fplResolveIPAddressV4ByHostname(const char *inHostname, fplNetworkIPAddressV4 *outAddress); bool fplResolveIPAddressV6ByHostname(const char *inHostname, fplNetworkIPAddressV6 *outAddress); bool fplResolveHostnameByIPAddressV4(const fplNetworkIPAddressV4 *inAddress, const size_t maxOutHostnameLen, char *outHostname); bool fplResolveHostnameByIPAddressV6(const fplNetworkIPAddressV6 *inAddress, const size_t maxOutHostnameLen, char *outHostname); // Better resolving / lookup typedef enum fplNetworkIPAddressType { fplNetworkIPAddressType_V4 = 0, fplNetworkIPAddressType_V6, } fplNetworkIPAddressType; typedef struct fplNetworkIPAddress { union { char[32] v4; char[128] v6; }; fplNetworkIPAddressType type; } fplNetworkIPAddress; bool fplParseIPAddress(const char *source, const size_t sourceLen, fplNetworkIPAddress *outAddress); bool fplResolveIPAddressByHostname(const char *inHostname, fplNetworkIPAddress *outAddress); bool fplResolveHostnameByIPAddress(const fplNetworkIPAddress *inAddress, const size_t maxOutHostnameLen, char *outHostname); |
ratchetfreak
The network events notification must be able to integrate seamlessly into the gui event notification. However it should also be possible to make another thread deal with the result.
Something like continuation queue is a good choice, with each command you also pass the queue that you want notified when the operation is done. With option to make it a GUI event or wait right then and there.
I am finalspace and do programming since more than 25 years, started on C64 and got serious with borland delphi. Nowadays i use C/C++ only.
Randy Gaul
I heavily agree with the idea to make your API deal with raw buffers the user can place arbitrary data into. There are two different problems here: protocol, and transport. You want to provide a transport layer -- get bytes from computer A to B with a good API. Then leave the protocol itself up to the user, or implement another higher level layer that consumes your transport to implement something specific (like HTTP message passing, or something else).