Question

In: Computer Science

How do I make a simple TCP python web client and web server using only "import...

How do I make a simple TCP python web client and web server using only "import socket"?

Basically, the client connects to the server, and sends a HTTP GET request for a specific file (like a text file, HTML page, jpeg, png etc), the server checks for the file and sends a copy of the data to the client along with the response headers (like 404 if not found, or 200 if okay etc).

The process would be:

  1. You first run your server, and it will bind itself to a predetermined port number, or will have the system choose it and then it will print it out (so that you know where the server is when you go to run the client). Your server then waits for your client to attempt a connection.
  2. You then run your client specifying a URL like: http://host:port/file where host is the host your server is on (like localhost if it’s on the same system as your client), port is the port number the server is waiting for connections on, and file is the name of the file you want to retrieve from your server. You can also provide the parameters individually.
  3. Your client makes a TCP connection to the given host on the given port, establishing a connection to your server.
  4. Your client then sends a standard HTTP 1.1 GET request to the server through its connection for the given file
  5. Your server receives this request from the connection and makes sure that it’s good. (It’s a supported request - GET, that the protocol version is appropriate, etc.)
  6. Your server attempts to open the given file requested by your client, relative to its current directory, and responds with a 404 response if the file is not found. If all is good, your server responds with an appropriate 200 response and required headers.
  7. Your server then reads the file in chunks and writes the chunks down the socket back to your client until it has transmitted the entire file and closes off the file on its end.
  8. Your client receives the headers from your server. If there is an error, it reports the error and exits.
  9. If all is well, your client receives the file data from your server. It opens up a file of the same name locally and begins to write what it reads from the socket into the file until it has received the file in its entirety.
  10. When done, your client closes the new file and exits, and your server closes the connection to your client and starts waiting for another connection request.

Solutions

Expert Solution

Import socket :
Socket programming is a way of connecting two nodes on a network to communicate with each other. One socket(node) listens on a particular port at an IP, while other socket reaches out to the other to form a connection. Server forms the listener socket while client reaches out to the server.
They are the real backbones behind web browsing. In simpler terms there is a server and a client.

Socket programming is started by importing the socket library and making a simple socket.

Example :
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

Sockets can be configured to act as a server and listen for incoming messages, or connect to other applications as a client. After both ends of a TCP/IP socket are connected, communication is bi-directional.

Implementation :

sample program, based on the one in the standard library documentation, receives incoming messages and echos them back to the sender. It starts by creating a TCP/IP socket.

import socket
import sys

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

Then bind() is used to associate the socket with the server address. In this case, the address is localhost, referring to the current server, and the port number is 10000.

# Bind the socket to the port
server_address = ('localhost', 10000)
print >>sys.stderr, 'starting up on %s port %s' % server_address
sock.bind(server_address)

Calling listen() puts the socket into server mode, and accept() waits for an incoming connection.

# Listen for incoming connections
sock.listen(1)

while True:
# Wait for a connection
print >>sys.stderr, 'waiting for a connection'
connection, client_address = sock.accept()

accept() returns an open connection between the server and client, along with the address of the client. The connection is actually a different socket on another port (assigned by the kernel). Data is read from the connection with recv() and transmitted with sendall().

try:
print >>sys.stderr, 'connection from', client_address

# Receive the data in small chunks and retransmit it
while True:
data = connection.recv(16)
print >>sys.stderr, 'received "%s"' % data
if data:
print >>sys.stderr, 'sending data back to the client'
connection.sendall(data)
else:
print >>sys.stderr, 'no more data from', client_address
break
  
finally:
# Clean up the connection
connection.close()

When communication with a client is finished, the connection needs to be cleaned up using close(). This example uses a try:finally block to ensure that close() is always called, even in the event of an error.


Lets see what is Echo Client :

The client program sets up its socket differently from the way a server does. Instead of binding to a port and listening, it uses connect() to attach the socket directly to the remote address.

import socket
import sys

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect the socket to the port where the server is listening
server_address = ('localhost', 10000)
print >>sys.stderr, 'connecting to %s port %s' % server_address
sock.connect(server_address)

After the connection is established, data can be sent through the socket with sendall() and received with recv(), just as in the server.

try:
  
# Send data
message = 'This is the message. It will be repeated.'
print >>sys.stderr, 'sending "%s"' % message
sock.sendall(message)

# Look for the response
amount_received = 0
amount_expected = len(message)
  
while amount_received < amount_expected:
data = sock.recv(16)
amount_received += len(data)
print >>sys.stderr, 'received "%s"' % data

finally:
print >>sys.stderr, 'closing socket'
sock.close()

When the entire message is sent and a copy received, the socket is closed to free up the port.


Now we will look what is Client and Server Together :

The client and server should be run in separate terminal windows, so they can communicate with each other.
The server output is:

$ python ./socket_echo_server.py

starting up on localhost port 10000
waiting for a connection
connection from ('127.0.0.1', 52186)
received "This is the mess"
sending data back to the client
received "age. It will be"
sending data back to the client
received " repeated."
sending data back to the client
received ""
no more data from ('127.0.0.1', 52186)
waiting for a connection

The client output is:

$ python socket_echo_client.py

connecting to localhost port 10000
sending "This is the message. It will be repeated."
received "This is the mess"
received "age. It will be"
received " repeated."
closing socket
$


Easy Client Connections :
TCP/IP clients can save a few steps by using the convenience function create_connection() to connect to a server. The function takes one argument, a two-value tuple containing the address of the server, and derives the best address to use for the connection.

import socket
import sys

def get_constants(prefix):
"""Create a dictionary mapping socket module constants to their names."""
return dict( (getattr(socket, n), n)
for n in dir(socket)
if n.startswith(prefix)
)

families = get_constants('AF_')
types = get_constants('SOCK_')
protocols = get_constants('IPPROTO_')

# Create a TCP/IP socket
sock = socket.create_connection(('localhost', 10000))

print >>sys.stderr, 'Family :', families[sock.family]
print >>sys.stderr, 'Type :', types[sock.type]
print >>sys.stderr, 'Protocol:', protocols[sock.proto]
print >>sys.stderr

try:
  
# Send data
message = 'This is the message. It will be repeated.'
print >>sys.stderr, 'sending "%s"' % message
sock.sendall(message)

amount_received = 0
amount_expected = len(message)
  
while amount_received < amount_expected:
data = sock.recv(16)
amount_received += len(data)
print >>sys.stderr, 'received "%s"' % data

finally:
print >>sys.stderr, 'closing socket'
sock.close()

create_connection() uses getaddrinfo() to find candidate connection parameters, and returns a socket opened with the first configuration that creates a successful connection. The family, type, and proto attributes can be examined to determine the type of socket being returned.

$ python socket_echo_client_easy.py

Family : AF_INET
Type : SOCK_STREAM
Protocol: IPPROTO_TCP

sending "This is the message. It will be repeated."
received "This is the mess"
received "age. It will be"
received " repeated."
closing socket


Choosing an Address for Listening :

It is important to bind a server to the correct address, so that clients can communicate with it. The previous examples all used 'localhost' as the IP address, which limits connections to clients running on the same server. Use a public address of the server, such as the value returned by gethostname(), to allow other hosts to connect. This example modifies the echo server to listen on an address specified via a command line argument.

import socket
import sys

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Bind the socket to the address given on the command line
server_name = sys.argv[1]
server_address = (server_name, 10000)
print >>sys.stderr, 'starting up on %s port %s' % server_address
sock.bind(server_address)
sock.listen(1)

while True:
print >>sys.stderr, 'waiting for a connection'
connection, client_address = sock.accept()
try:
print >>sys.stderr, 'client connected:', client_address
while True:
data = connection.recv(16)
print >>sys.stderr, 'received "%s"' % data
if data:
connection.sendall(data)
else:
break
finally:
connection.close()

A similar modification to the client program is needed before the server can be tested.

import socket
import sys

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect the socket to the port on the server given by the caller
server_address = (sys.argv[1], 10000)
print >>sys.stderr, 'connecting to %s port %s' % server_address
sock.connect(server_address)

try:
  
message = 'This is the message. It will be repeated.'
print >>sys.stderr, 'sending "%s"' % message
sock.sendall(message)

amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
data = sock.recv(16)
amount_received += len(data)
print >>sys.stderr, 'received "%s"' % data

finally:
sock.close()

After starting the server with the argument farnsworth.hellfly.net, the netstat command shows it listening on the address for the named host.

$ host farnsworth.hellfly.net

farnsworth.hellfly.net has address 192.168.1.17

$ netstat -an

Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
...
tcp4 0 0 192.168.1.17.10000 *.* LISTEN
...

Running the the client on another host, passing farnsworth.hellfly.net as the host where the server is running, produces:

$ hostname

homer

$ python socket_echo_client_explicit.py farnsworth.hellfly.net

connecting to farnsworth.hellfly.net port 10000
sending "This is the message. It will be repeated."
received "This is the mess"
received "age. It will be"
received " repeated."

And the server output is:

$ python ./socket_echo_server_explicit.py farnsworth.hellfly.net

starting up on farnsworth.hellfly.net port 10000
waiting for a connection
client connected: ('192.168.1.8', 57471)
received "This is the mess"
received "age. It will be"
received " repeated."
received ""
waiting for a connection

Many servers have more than one network interface, and therefore more than one IP address. Rather than running separate copies of a service bound to each IP address, use the special address INADDR_ANY to listen on all addresses at the same time. Although socket defines a constant for INADDR_ANY, it is an integer value and must be converted to a dotted-notation string address before it can be passed to bind(). As a shortcut, use the empty string '' instead of doing the conversion.

import socket
import sys

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Bind the socket to the address given on the command line
server_address = ('', 10000)
sock.bind(server_address)
print >>sys.stderr, 'starting up on %s port %s' % sock.getsockname()
sock.listen(1)

while True:
print >>sys.stderr, 'waiting for a connection'
connection, client_address = sock.accept()
try:
print >>sys.stderr, 'client connected:', client_address
while True:
data = connection.recv(16)
print >>sys.stderr, 'received "%s"' % data
if data:
connection.sendall(data)
else:
break
finally:
connection.close()

To see the actual address being used by a socket, call its getsockname() method. After starting the service, running netstat again shows it listening for incoming connections on any address.

$ netstat -an

Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
...
tcp4 0 0 *.10000 *.* LISTEN
...


Related Solutions

TCP client and server using C programming I am having trouble on how to read in...
TCP client and server using C programming I am having trouble on how to read in the IP adress and port number from the terminal Example: Enter IP address: 127.0.0.1 Enter Port Number: 8000 in both client and server code. How do can I make I can assign the Ip address and port number using the example above. the error I get is that the client couldn't connect with the server whenever i get the port number from the user...
How to create a FTP server using python and TCP Ports How to create a FTP...
How to create a FTP server using python and TCP Ports How to create a FTP server using python and UDP Ports
In this assignment, you will develop a simple Web server in Python that is capable of...
In this assignment, you will develop a simple Web server in Python that is capable of processing only one request. Specifically, your Web server will (i) create a connection socket when contacted by a client (browser); (ii) receive the HTTP request from this connection; (iii) parse the request to determine the specific file being requested; (iv) get the requested file from the server’s file system; (v) create an HTTP response message consisting of the requested file preceded by header lines;...
Suppose a TCP client needs to send 3 packets to the TCP server. Before sending the...
Suppose a TCP client needs to send 3 packets to the TCP server. Before sending the first packet, the estimated RTT is 50 ms, and the estimated deviation of the sample RTT is 10 ms. The parameters α= 0.1, and β = 0.2. The measured sample RTT for the three packets are 60ms, 70 ms, and 40 ms, respectively. Please compute the time out value that was set for each packet right after it is being transmitted out.
Assume a client uses TCP to send data to a server. The TCP header has 12...
Assume a client uses TCP to send data to a server. The TCP header has 12 bytes of options and 99 bytes of data. [Please don't forget Ethernet Type/Len field is 2 bytes in size.] 1. Calculate the total number of bytes passed to the IP layer by the TCP layer. 2. Calculate the total number of bytes passed to the network layer by the IP layer, assuming the IP layer has no options. 3. Calculate the total number of...
Make a modest or simple Web page using Python flask. The basic components of HTML should...
Make a modest or simple Web page using Python flask. The basic components of HTML should be included. The Web page should have at least 3 Headings(<h1>), paragraph (<p>), comments (<!-- -->), ordered list, unordered list, three links to website, and should display time & date. Example: <html>     <head>         <title>Page Title</title>     </head> <body>     ..new page content.. </body> </html>
write a skeleton Python TCP servers as follows: Multi-threaded concurrent TCP server using Python’s low-level socket...
write a skeleton Python TCP servers as follows: Multi-threaded concurrent TCP server using Python’s low-level socket module and Python’s threading library Python sockets API: s = socket(), s.bind(), s.listen(), remote_socket, remote_addr = s.accept() Python threading API: thread = threading.Thread(target, args, daemon), thread.start()
Greetings, Consider a client server model.The server sends the message 'I am the server' to client....
Greetings, Consider a client server model.The server sends the message 'I am the server' to client. Describe and compare in details how the client and server exchange these messages using internet domain in the following two modes. a) connection-oriented modes b) connectionless-oriented modes
The goal of this lab is to write a simple, but functional, web server that is...
The goal of this lab is to write a simple, but functional, web server that is capable of sending files to a web browser on request. The web server must create a listening socket and accept connections. It must implement just enough of the HTTP/1.1 protocol to enable it to read requests for files and to send the requested files. It should also be able to send error responses to the client when appropriate. It would be useful to see...
To be written in Python: Connect to a TCP-based Quote of the Day server (see RFC...
To be written in Python: Connect to a TCP-based Quote of the Day server (see RFC 865) and obtain a random quote and print it to the console.
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT