When using ICE, it is imperative that the client uses client-side behavior, but in addition, it should act as a STUN server. Both ICE lite and full ICE implementations require the client to act as a STUN server.
In non-ICE contexts, a client using STUN for NAT traversal would only ever act as the originator, talking to a STUN-server to discover if it was behind a NAT. The client would only look for responses of success or failure to a request message that was sent to the server.
The reason ICE clients need to have STUN server capabilities comes from the use of ICE to discover network topologies. The best way to accomplish that is to have the connecting parties send STUN messages to one another and listen for responses.
Not only does this method rid incompatible connections, it will also discover new connections if one or many of the clients are located behind NATs. Moreover, the use of clients as servers allows strict NAT (think symmetric) discovery, and connections that can be created from them.
For clients to act as servers in an ICE context, the process is rather straightforward. When a client receives a STUN binding request it must immediately send back a response. This response must contain, for the purpose of NAT discovery for the originating client, the XOR-mapped address of the originator. The XOR mapped address is built by XORing the address and port of the received message by the entire magic cookie and the 16 MSB of the magic cookie respectively.
After sending this response, the receiving client will then send its own STUN check of the route by finding the matching candidate (or by creating a new candidate,) and then placing that candidate in the triggered check queue. Once the response for that check is received, the candidate pair for that route is valid. Thus, an ICE client acting as a STUN server allows proper NAT discovery and traversal.