socket programming

My note of socket programming

Binding
Extra final note about bind(): there are times when you won’t absolutely have to call it. If you are connect()ing to a remote machine and you don’t care what your local port is (as is the case with telnet where you only care about the remote port), you can simply call connect(), it’ll check to see if the socket is unbound, and will bind() it to an unused local port if necessary.

==============================

Socket file descriptor

Someone far away will try to connect() to your machine on a port that you are listen()ing on. Their connection will be queued up waiting to be accept()ed. You call accept() and you tell it to get the pending connection. It’ll return to you a brand new socket file descriptor to use for this single connection! That’s right, suddenly you have two socket file descriptors for the price of one! The original one is still listening on your port and the newly created one is finally ready to send() and recv().

=====================

Passing double/int pointer across the wire problem

double d = 3490.15926535;
send(s, &d, sizeof d, 0);  /* DANGER–non-portable! */

The receiver gets it like this:

double d;
recv(s, &d, sizeof d, 0);  /* DANGER–non-portable! */

Fast, simple—what’s not to like? Well, it turns out that not all architectures represent a double (or int) for that matter with the same bit representation or even the same byte ordering! The code is decidedly non-portable.

Sockets

This is how my protocol is supposed to work:

  1. Client says to server “hello, here’s my username”
  2. Server says to client “cool, here’s a random byte to encrypt”
  3. Client says to server “ok, I’ve encrypted the byte using the hash of the password my user provided, here’s the encrypted data”
  4. […]

This is how my protocol actually works:

  1. Client says to server “hello, here’s my username”
  2. Server says to client “cool, here’s a random byte to encrypt”
  3. Client says to server “ok, I’ve encrypted 0x00 using the hash of the…”
  4. Server says to client “wrong”
  5. [user restarts procedure without restarting client or server]
  6. Client says to server “hello, here’s my username again”
  7. Server says to client “cool, let’s re-use that old random byte since your connection hasn’t dropped in the mean time so I’ve no reason to suspect it’s been hijacked, here it is again for you”
  8. Client says to server “ok, I’ve encrypted 0x55 using the hash of the…”
  9. Server says to client “wrong”
  10. [user, getting increasingly impatient, tries a third time]
  11. Client says to server “hello, here’s my username a third time!”
  12. Server says to client “ok, again with the random byte, same one I’ve been using this whole time, here it is”
  13. Client says to server “ok, I’ve encrypted the random byte using the hash of the username and password, here’s the encrypted data”
  14. Server sometimes says to client “wrong”, but thinks to itself “correct!”, sometimes reports “correct” to the client and its own log.  If the former, the next login attempt will inevitably succeed and all’s well in the end anyway.

The numbers 0x00 and 0x55 mean absolutely nothing to my code.  I’m really confused by this.  I’m pretty sure it’s a case of the client not reading everything from the socket before it starts reading the ‘random byte’ packet, but the weird thing is that the socket shouldn’t have any data on it before the random byte packet.  The server doesn’t send any data before the random byte packet.

I’m so confused :(