Network Basics:

TCP/IP

Python's networking modules primarily support TCP/IP

Both protocols are supported using "sockets"

Ports

Socket programming general sequence

The socket Module

Creating a socket

A socket is created through the socket (family, type, [ proto ]) call; family is one of the above mentioned address families: AF UNIX and AF INET, type is represented through the following

constants: SOCK STREAM, SOCK DGRAM and SOCK RAW. proto argument is optional and defaults to 0. We see that socket() function returns a socket

in the specified domain with the specifieed type. Because the constants mentioned above are contained in the socket module, it will be better if they are used with the socket.CONSTANT notation.

Without doing so, the interpreter may generate an error.

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

 SOCK_STREAM         Stream socket (TCP)
 SOCK_DGRAM          Datagram socket (UDP)
 SOCK_RAW            Raw socket

 

sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)

 

Connecting a socket and data transfer

A server from our point of view is a process which listen on a specified port. We may call the association port, process as a service. When another process wants to meet the server or

use a specific service it must connect itself to the address and portnumber specified by the server. This is done calling the socket method connect(address ), where address is a pair

(host, port) in the Internet domain and a pathname in the UNIX domain.

sock.connect(('localhost', 8000))

 

If the service is unavailable or the server don't want to talk with the client process a socket.error- (111, 'Connection refused') is issued. Elsewhere, after the connection is established with the

desired server, data is sent and received with send(buffer, [ flags ]) and recv(buffer, [flags ]) methods. These methods accepts as mandatory parameter the size of the buffer in bytes and some optional flags

which are UNIX specific.

 

Binding a name to socket

The socket, after creation, is nameless, though it have an associated descriptor. Before it can be used it must be bind to a proper address since this is the only way a foreign process may

reference it. The bind(address ) method is used to name a socket. The meaning of the address is explained above. Next call will bind a socket in the Internet domain with address

composed from hostname localhost and port number 8000 :

sock.bind(('localhost', 8000))

Please take care when typing: indeed there are two pairs of parenthesis. Doing elsewhere the interpreter will issue a TypeError. The purpose of the two pairs of parenthesis is simple:

address is a tuple containing a string and an integer. The hostname must be properly picked, the best method is to use gethostname() routine in order to assure host independence and portability.

 

Listening and accepting connections

Once we have a socket with a proper name bound to it, next step is calling the listen(queue ) method. It instructs the socket to passively listen on port port . listen() take as parameter

an integer representing the maximum queued connection. This argument should be at least 1 and maximum, system-dependent, 5. Until now we have a socket with a proper bounded

address. When a connection request arrives, the server decide whether it will be accepted or not. Accepting a connection is made through the accept() method. It takes no parameter

but it returns a tuple (clientsocket, address) where clientsocket is a new socket server uses to communicate with the client and address is the client's address. accept() normally

blocks until a connection is realized. This behavior can be overridden running the method in a separate thread, collecting the new created socket descriptors in a list and process them in

order. Meantime, the server can do something else. The above mentioned methods are used as follows:

sock.listen(5)

clisock, address = sock.accept()

The code instructs the socket on listening with a queue of five connections and accept all incoming  calls. As you can see, accept() returns a new socket that will be used in further

data exchanging. Using the chain bind-listen-accept we create TCP servers. Remember, a TCP socket is connection-oriented; when a client wants to speak to a particular server it must

connect itself, wait until the server accepts the connection, exchange data then close. This is modeling a phone call: the client dial the number, wait till the other side establish the

connection, speak then quit.

 

socket methods summary

 

Utility Functions

Comments

 

In-lab Assignment

Implement both Client/Server parts of a communication such that Client will send two integers, each of which is a two-digit decimal number. And  Server will reply with the sum of those integers.

Client may take the two integers as an argument input to the program or in run-time from the user. After receiving the reply of the Server, Client will show the user final result.

Tip 1: Use str() function to convert an integer to a string, and use int() function to convert a string to an integer.

Tip 2: You have to specify how long a message you are expecting to receive at recv(n) function. Since you can get full mark for adding up two-digit decimal numbers, you might want to use recv(2) for two times so you can get two strings, each of which has length of 2 and contains the number the client sends.

Tip 3: Learn from the examples in last lab and start from modifying them.

After you finish the programs, you have to raise your hand and let the TA check you out.

 

Take-home thinking

1.  Instead of only summing two-digit numbers, take the any number of digits from the user and execute it on the Server side.

2.  Make the Server Running and accepting connections forever.