coding stock image

Up Your Skill in Python by Creating a Client-Server Application with Websockets Effortlessly

Introduction: Python Websockets

In this post, I want to show and explain how to up your skill in Python Websockets. Specifically, you will learn the basics of Websockets by creating a client-server application. By reading this post, you will understand how to send and receive data in a client-server python application. Cool right!? On to it then.

This is a continuation from a previous post I wrote last month, A SHORT AND SIMPLE GUIDE TO WRITING A NETWORK CLIENT APPLICATION IN PYTHON. My recommendation is to start there if you have no experience with WebSockets.

Additionally, I referenced the official Python documentation for the socket library extensively. It would be in your interest to give it your attention as you learn this topic. Here is the Python Websockets link for your reference. Now lets actually get started.

The Server Program

Let’s begin by first writing the server program. I will show the entire code here and then explain the major pieces.

import socket
import time


BUFFERSIZE = 10

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 50000))
s.listen(5)

while True:
    # now our endpoint knows about the OTHER endpoint.
    clientsocket, address = s.accept()
    print(f"Connection from {address} has been established.")

    from_client = ''

    login_msg = clientsocket.recv(2048)
    from_client += login_msg.decode("utf-8")

    if from_client == 'password':
        msg = "Access Granted"
        clientsocket.send(bytes(msg,"utf-8"))
        
        msg = f"{len(msg):<{BUFFERSIZE}}"+msg
        clientsocket.send(bytes(msg,"utf-8"))
    else:
        break
    
    while True:
        time.sleep(5)
        msg = f"The time is {time.asctime()}"
        msg = f"{len(msg):<{BUFFERSIZE}}"+msg

        print(msg)

        clientsocket.send(bytes(msg,"utf-8"))

fail_msg = "Access Denied"
clientsocket.send(bytes(fail_msg,"utf-8"))
clientsocket.close()
print(f"Connection from {address} has been closed.")

When using any library in Python, it must be imported at the beginning of the program with the import keyword. Since we are using the Python Websockets library, we call import socket.

The job of this server program is to stream the time to clients who connect to it. Therefore, we are using the Python time library, which we call with import time.

Considering that the server is streaming data to connected clients, we initialize a variable called BUFFERSIZE to an integer of 10.

Function Call

The next line is the function call that creates a socket to a given address and the socket type.

Then, the bind function is called which as you may have guessed, binds the socket to the address. The gethostname() retrieves the hostname of the machine that the Python interpreter is currently running and returns this as a string. 50000 is the port that communication occurs.

The listen function permits the server to accept connections. The value of 5 specifies the number of unaccepted connections that the system will allow before refusing new connections.

Flow Control

We begin with a While True statement. The accept() function returns a tuple of the connecting socket and connecting address. We then print the line shown on the server side.

Then we create an empty string to store data sent from the client.

The recv(2048) function receives data from a socket and returns bytes. The value inside is how many bytes can be received. These bytes are stored inside the login_msg variable. Then, we decode the bytes and store them.

The if statement checks if the from_client variable is ‘password’. If it is, ‘Access Granted’ is sent to the connecting socket. The length of the message up to 10 bytes plus the message is sent to the socket also.

If not, we break out of the while loop. When we break out of the loop, we skip to the last four lines of code. “Access Denied” is sent to the socket, and the socket connection is closed by the server. The print statement is seen on the server-side.

If the correct password is sent by the client, we start the 2nd While True statement. This loop starts by sleeping for five seconds, then stores the print statement, the time, and length of the message inside the msg variable. Next, the msg is printed on the server-side. This same data is sent to the connecting socket.

Let’s check out what the output will look like. However, this will not work without the client application running. I show it here for your motivation.

Server Showing Successful Connection of Client
Server Showing Failed Connection of Client

The Client Program

Next, I reveal the client program.

import socket

BUFFERSIZE = 10

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((socket.gethostname(), 50000))

access_msg = input("Please enter password to obtain access: ")
client.send(bytes(access_msg,"utf-8"))

server_msg = ''
server_msg = client.recv(16)
full_server_msg = server_msg.decode("utf-8")

if full_server_msg == 'Access Granted':

    while True:
        full_msg = ''
        new_msg = True
        while True:
            msg = client.recv(16)
            if new_msg:
                print("new msg len:",msg[:BUFFERSIZE])
                msglen = int(msg[:BUFFERSIZE])
                print(f"full message length: {msglen}")
                new_msg = False

            full_msg += msg.decode("utf-8")

            if len(full_msg)-BUFFERSIZE == msglen:
                print("full message received")
                print(full_msg[BUFFERSIZE:])
                new_msg = True
                full_msg = ""
else:
    print(full_server_msg)
    client.close()

The first four lines are essentially the same as the server program. In the input statement, we ask the client to enter a password which is then stored inside a variable. This data is sent to the server-side.

Then, a variable is made with an empty string. This will store a message sent from the server.

Flow Control

If the server sends ‘Access Granted’, we continue into a While True statement. If not, we skip down to the bottom else statement. We print any message sent by the server and close the socket connection.

If we are granted access, a new empty string is declared inside the while loop. When we receive a new message, we enter yet another While True statement.

We wait to receive up to 16 bytes of data and store this inside msg. Then we enter an if statement. If there is a new message, we print the new message and full message length for the client. We also declare a new variable called msglen to store the integer value of the msg up to the buffer size.

The message is decoded and added to the full message variable. If the length of the full message minus the buffer size is the same as the msglen, we print the full message.

Client Showing Successful Connection to the Server
Client Showing Failed Connection to the Server

Conclusion

Here we are near the end of this post. I hope that you learned something about Python Websockets through this example. If you enjoyed this post, consider checking out a similar post that digs into the concept of the client-server communication. Happy learning 😀

0 0 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x