|
Socket Pitfalls
There are a few situations to be aware of when writing socket communication applications.
Transactions
In many situations, when sending data via sockets, it is quite sufficient to know that the data has left your computer. To support network communiactions, operating systems have large outgoing data buffers (although I think their size can be changed using some low level socket options such as setsockopt or ioctlsocket); you can place a lot of data in an output socket without getting a write block even though the connection could break. In this situation, none of the data will leave the machine.
Now when you're writing a transaction-sensitive tool, like a phone-based credit card terminal system, that's something completely different. There are a million evil things that can befall a solitary packet floating around the cyberspace after being spat out of your machine's network card. It can get lost on its way, it can get rejected by a server application that's just crashed, there can be a power failure while the remote machine processes the packet etc. etc. If you don't want spend the rest of your life paying losses to the bank using your system, you had better wait for an acknowledgement response.
This is the sad truth of remote computation: while both machines are talking, you know everything's fine. One machine stops talking, the other has no way (without restoring the communication) to find out what part of communication since the last handshake has got through the line and through the remote application.
There's a similar problem with disconnection; you can never be absolutely sure that the other side has disconnected gracefully, because each side would have to wait for the other side's confirmation and both machines would deadlock forever.
The disconnection protocol usually communication to go like this:
1. One side issues close()
2. Disconnection message sent to other side
3. Other side detects disconnection and issues close()
4. Other side sends disconnection message to first side.
Unfortunately, this protocol cannot be relied on all the time because of possible breaks in connections. The basic rule is that enough bidirectional communication must have taken place to make sure on both sides that the potentially ungraceful shutdown will not have serious negative effect on either side.
A somewhat stricter formulation: the communication protocol and its implementation should always ensure that an ungraceful remote shutdown at any time doesn't endanger stability and transaction data on either side.
Custom Protocols
Because of the situations listed above, it may be necessary to create a socket communication protocol to verify what data has be received on the other side of the connection. For example, the receiving side can send back a CRC or hash of the received data. Then the sender can verify that the information was received correctly. TCP/IP protocol handles transmission issues on the packet level, but due to the buffering situation described above, other efforts need to be made to ensure the data has been received.
Network latency
Along with breaks in connection, you will have to account for network latency. Be sure to test your applications on multiple networks, especially slow and error-prone connections. Also, there are many optional parameters to U++ socket functions and methods that allow custom timeouts to be specified for waiting for connections and the such.
Sharing Ports
Processes cannot share ports with other processes within the computer. When a process is connected to a port, other processes will not be able to use that port. In this case, alternate ports will have to be used.
|