Socket Communications¶
This exercise will walk you through your first client-server interaction using basic Python sockets
Client Communications¶
First, connect and send a message, then tell the server you’re done sending:
>>> import socket
>>> streams = [info
... for info in socket.getaddrinfo('crisewing.com', 'http')
... if info[1] == socket.SOCK_STREAM]
>>> info = streams[0]
>>> cewing_socket = socket.socket(*info[:3])
>>> cewing_socket.connect(info[-1])
>>> msg = "GET / HTTP/1.1\r\n"
>>> msg += "Host: crisewing.com\r\n\r\n"
>>> cewing_socket.sendall(msg)
>>> cewing_socket.shutdown(socket.SHUT_WR)
Then, receive a reply, iterating until it is complete:
>>> buffsize = 4096
>>> response = ''
>>> done = False
>>> while not done:
... msg_part = cewing_socket.recv(buffsize)
... if len(msg_part) < buffsize:
... done = True
... cewing_socket.close()
... response += msg_part
...
>>> len(response)
19427
>>> cewing_socket.close()
When you are finished with a connection, you should always close it!
Server Side¶
What about the other half of the equation?
Construct a Socket¶
For the time being, don’t bother typing this. You’ll do it again shortly
Again, we begin by constructing a socket. Since we are actually the server this time, we get to choose family, type and protocol:
>>> server_socket = socket.socket(
... socket.AF_INET,
... socket.SOCK_STREAM,
... socket.IPPROTO_TCP)
...
>>> server_socket
<socket._socketobject object at 0x100563c90>
Bind and Listen¶
Our server socket needs to be bound to an address. This is the IP Address and Port to which clients must connect:
>>> address = ('127.0.0.1', 50000)
>>> server_socket.bind(address)
>>> server_socket.listen(1)
Terminology Note: In a server/client relationship, the server binds to an address and port. The client connects
listen
prepares our socket to receive connections from clients.- The argument to
listen
is the backlog - The backlog is the maximum number of connection requests that the socket will queue
- Once the limit is reached, the socket refuses new connections.
Accept Incoming Messages¶
When a socket is listening, it can receive incoming connection requests:
>>> connection, client_address = server_socket.accept() # this blocks until a client connects
>>> connection.recv(16)
- The
connection
returned by a call toaccept
is a new socket. This new socket is used to communicate with the client - The
client_address
is a two-tuple of IP Address and Port for the client socket - When a connection request is ‘accepted’, it is removed from the backlog queue.
Send a Reply¶
The same socket that received a message from the client may be used to return a reply:
>>> connection.sendall("message received")
>>> connection.shutdown(socket.SHUT_WR)
Clean Up¶
Once a transaction between the client and server is complete, the
connection
socket should be closed:
>>> connection.close()
Note that the server_socket
is never closed as long as the server
continues to run.
Getting the Flow¶
The flow of this interaction can be a bit confusing. Let’s see it in action step-by-step.
Open a second python interpreter and place it next to your first so you can see both of them at the same time.
Create a Server¶
Start Typing Now
In your first python interpreter, create a server socket and prepare it for connections:
>>> server_socket = socket.socket(
... socket.AF_INET,
... socket.SOCK_STREAM,
... socket.IPPROTO_IP)
>>> server_socket.bind(('127.0.0.1', 50000))
>>> server_socket.listen(1)
>>> conn, addr = server_socket.accept()
At this point, you should not get back a prompt. The server socket is waiting for a connection to be made.
Create a Client¶
In your second interpreter, create a client socket and prepare to send a message:
>>> import socket
>>> client_socket = socket.socket(
... socket.AF_INET,
... socket.SOCK_STREAM,
... socket.IPPROTO_IP)
Before connecting, keep your eye on the server interpreter:
>>> client_socket.connect(('127.0.0.1', 50000))
Send a Message Client->Server¶
As soon as you made the connection above, you should have seen the prompt
return in your server interpreter. The accept
method finally returned a
new connection socket.
When you’re ready, type the following in the client interpreter:
>>> client_socket.sendall("Hey, can you hear me?")
>>> client_socket.shutdown(socket.SHUT_WR)
Receive and Respond¶
Back in your server interpreter, go ahead and receive the message from your client:
>>> conn.recv(32)
'Hey, can you hear me?'
Send a message back, and then close up your connection:
>>> conn.sendall("Yes, I hear you.")
>>> conn.close()
Finish Up¶
Back in your client interpreter, take a look at the response to your message, then be sure to close your client socket too:
>>> client_socket.recv(32)
'Yes, I hear you.'
>>> client_socket.close()
And now that we’re done, we can close up the server too (back in the server interpreter):
>>> server_socket.close()
Congratulations!¶
You’ve run your first client-server interaction
Now, you’re ready to write a basic echo server and client