Skip to main content

Server/Client Communication-python


The basic mechanisms of client-server setup are:

  • A client app send a request to a server app. 
  • The server app returns a reply. 
Some of the basic data communications between client and server are:
  • File transfer - sends name and gets a file. 
  • Web page - sends url and gets a page. 
  • Echo - sends a message and gets it back. 
Client server communication uses socket.

             To connect to another machine, we need a socket connection.
What's a connection? 
A relationship between two machines, where two pieces of software know about each other. Those two pieces of software know how to communicate with each other. In other words, they know how to send bits to each other.
A socket connection means the two machines have information about each other, including network location (IP address) and TCP port. (If we can use anology, IP address is the phone number and the TCP port is the extension). 
A socket is an object similar to a file that allows a program to accept incoming connections, make outgoing connections, and send and receive data. Before two machines can communicate, both must create a socket object.
A socket is a resource assigned to the server process. The server creates it using the system call socket(), and it can't be shared with other processes.
Stream Sockets
Stream sockets provide reliable two-way communication similar to when we call someone on the phone. One side initiates the connection to the other, and after the connection is established, either side can communicate to the other.
In addition, there is immediate confirmation that what we said actually reached its destination. 
Stream sockets use a Transmission Control Protocol (TCP), which exists on the transport layer of the Open Systems Interconnection (OSI) model. The data is usually transmitted in packets. TCP is designed so that the packets of data will arrive without errors and in sequence. 
Webservers, mail servers, and their respective client applications all use TCP and stream socket to communicate.
Datagram Sockets
Communicating with a datagram socket is more like mailing a letter than making a phone call. The connection is one-way only and unreliable. 
If we mail several letters, we can't be sure that they arrive in the same order, or even that they reached their destination at all. Datagram sockets use User Datagram Protocol (UDP). Actually, it's not a real connection, just a basic method for sending data from one point to another.
Datagram sockets and UDP are commonly used in networked games and streaming media. 
Though in this section, we mainly put focus on applications that maintain connections to their clients, using connection-oriented TCP, there are cases where the overhead of establishing and maintaining a socket connection is unnecessary.
For example, just to get the data, a process of creating a socket, making a connection, reading a single response, and closing the connection, is just too much. In this case, we use UDP. 
Services provided by UDP are typically used where a client needs to make a short query of a server and expects a single short response. To access a service from UDP, we need to use the UDP specific system calls, sendto() and recvfrom() instead of read() and write() on the socket. 
UDP is used by app that doesn't want reliability or bytestreams.
Voice-over-ip (unreliable) such as conference call. (visit VoIP) 
DNS, RPC (message-oriented) 
DHCP (bootstrapping) 

Socket 
Socket is a way of speaking to other programs using standard file descriptors. 
Where do we get the file descriptor for network communication? 
Well, we make a call to the socket() system routine.
After the socket() returns the socket descriptor, we start communicate through it using the specialized send()/recv() socket API calls. 
A TCP socket is an endpoint instance 
A TCP socket is not a connection, it is the endpoint of a specific connection. 
A TCP connection is defined by two endpoints aka sockets. 
The purpose of ports is to differentiate multiple endpoints on a given network address. 

The port numbers are encoded in the transport protocol packet header, and they can be readily interpreted not only by the sending and receiving computers, but also by other components of the networking infrastructure. In particular, firewalls are commonly configured to differentiate between packets based on their source or destination port numbers as in port forwarding. 

It is the socket pair (the 4-tuple consisting of the client IP address, client port number, server IP address, and server port number) that specifies the two endpoints that uniquely identifies each TCP connection in an internet. 

Only one process may bind to a specific IP address and port combination using the same transport protocol. Otherwise, we'll have port conflicts, where multiple programs attempt to bind to the same port numbers on the same IP address using the same protocol. 
Server Socket
create a socket - Get the file descriptor! 
bind to an address -What port am I on? 
listen on a port, and wait for a connection to be established. 
accept the connection from a client. 
send/recv - the same way we read and write for a file. 
shutdown to end read/write. 
close to releases data. 
Client Socket
create a socket. 
bind* - this is probably be unnecessary because you're the client, not the server. 
connect to a server. 
send/recv - repeat until we have or receive data 
shutdown to end read/write. 
close to releases data. 
Simple Socket Creation and Communication in Python
In the following code, the server sends the current time string to the client:
# server.py 
import socket                                         
import time
# create a socket object
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
# get local machine name
host = socket.gethostname()                           
port = 9999                                           
# bind to the port
serversocket.bind((host, port))                                  
# queue up to 5 requests
serversocket.listen(5)                                           
while True:
    # establish a connection
    clientsocket,addr = serversocket.accept()      
    print("Got a connection from %s" % str(addr))
    currentTime = time.ctime(time.time()) + "\r\n"
    clientsocket.send(currentTime.encode('ascii'))
    clientsocket.close()
#########################################################################
# client.py  
import socket
# create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
# get local machine name
host = socket.gethostname()                           
port = 9999
# connection to hostname on the port.
s.connect((host, port))                               
# Receive no more than 1024 bytes
tm = s.recv(1024)                                     
s.close()
print("The time got from the server is %s" % tm.decode('ascii'))
The output from the run should look like this:
$ python server.py &
Got a connection from ('127.0.0.1', 54597)
$ python client.py  
The time got from the server is Wed Dec 29 19:14:15 2017

Here is the summary of the key functions from socket - Low-level networking interface:
socket.socket(): Create a new socket using the given address family, socket type and protocol number. 
socket.bind(address): Bind the socket to address. 
socket.listen(backlog): Listen for connections made to the socket. The backlog argument specifies the maximum number of queued connections and should be at least 0; the maximum value is system-dependent (usually 5), the minimum value is forced to 0. 
socket.accept(): The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection.
At accept(), a new socket is created that is distinct from the named socket. This new socket is used solely for communication with this particular client.
For TCP servers, the socket object used to receive connections is not the same socket used to perform subsequent communication with the client. In particular, the accept() system call returns a new socket object that's actually used for the connection. This allows a server to manage connections from a large number of clients simultaneously. 
socket.send(bytes[, flags]): Send data to the socket. The socket must be connected to a remote socket. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. 
socket.colse(): Mark the socket closed. all future operations on the socket object will fail. The remote end will receive no more data (after queued data is flushed). Sockets are automatically closed when they are garbage-collected, but it is recommended to close() them explicitly. 

Note that the server socket doesn't receive any data. It just produces client sockets. Each clientsocket is created in response to some other client socket doing a connect() to the host and port we're bound to. As soon as we've created that clientsocket, we go back to listening for more connections.

Echo Server
This is an echo server: the server that echoes back all data it receives to a client that sent it.
Server:
# echo_server.py
import socket
host = ''        # Symbolic name meaning all available interfaces
port = 12345     # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
while True:
    data = conn.recv(1024)
    if not data: break
    conn.sendall(data)
conn.close()

Client:
# echo_client.py
import socket
host = socket.gethostname()    
port = 12345                   # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendall(b'Hello, world')
data = s.recv(1024)
s.close()
print('Received', repr(data))

Comments

  1. You made some good points there. I did a search on the topic and found most people will agree with your blog

    Also Visit this site for "The Best Python Certification"

    ReplyDelete
  2. I simply wanted to write down a quick word to say thanks to you for those wonderful tips and hints you are showing on this site.
    It’s great to come across a blog every once in a while that isn’t the same out of date rehashed material. Fantastic read.

    Python Training in Chennai | Python Training Institutes in Chennai

    ReplyDelete
  3. Your good knowledge and kindness in playing with all the pieces were very useful. I don’t know what I would have done if I had not encountered such a step like this.
    Python Training in Bangalore

    ReplyDelete

Post a Comment

Popular posts from this blog

Inter Process Communication(IPC)- Pipes

Interprocess communication (IPC) is a set of programming interfaces that allow a programmer to coordinate activities among different program processes that can run concurrently in an operating system. This allows a program to handle many user requests at the same time. Since even a single user request may result in multiple processes running in the operating system on the user's behalf, the processes need to communicate with each other. The IPC interfaces make this possible. Each IPC method has its own advantages and limitations so it is not unusual for a single program to use all of the IPC methods. pipe In computer programming, especially in UNIX operating systems, a pipe is a technique for passing information from one program process to another. Unlike other forms of interprocess communication (IPC), a pipe is one-way communication only. Basically, a pipe passes a parameter such as the output of one process to another process which accepts it as input. The system temporarily ho…

Inter Process Communication-Message Queue

Interprocess communication (IPC) is a set of programming interfaces that allow a programmer to coordinate activities among different program processes that can run concurrently in an operating system. This allows a program to handle many user requests at the same time. Since even a single user request may result in multiple processes running in the operating system on the user's behalf, the processes need to communicate with each other. The IPC interfaces make this possible. Each IPC method has its own advantages and limitations so it is not unusual for a single program to use all of the IPC methods. Message Based Communication Messages are a very general form of communication. Messages can be used to send and receive formatted data streams between arbitrary processes. Messages may have types. This helps in message interpretation. The type may specify appropriate permissions for processes. Usually at the receiver end, messages are put in a queue. Messages may also be formatted in …