image block
644 Views 0 Comments
Hey! You're back! It's awesome! So time to discover something new!
And in this post, we will discuss how sockets are working and how to implement them on our scripts. So come on, let's move.

What is this socket?

Socket - its software realization of the contact point between processes.
To make clear understanding what is this, we can review the similar term "port". Ports are using as external endpoints to communicate between hosts, then sockets for internal process communication. In internal usage, sockets have "socket descriptor" to handle communications, it's like the abstract reference to the source. But also, sockets have a part on networking communicate, using other resources like address and port. For this, we need more parameters than two descriptors between internal sockets.
So from this, we can set next definitions:
  • Socket descriptor - abstract reference to the source (in most case the simple integer)
  • Socket address - network address (IPv4/IPv6)
  • Socket port - reference to port of local node
Let's move to practice.

TCP sockets

I want to provide simple scripts with TCP and UDP servers and clients. But first, what the difference?
These two protocols have the same target, to deliver packets to the destination point. But the principles of work are completely different.
TCP rearranges data packets in the order specified and after each packet, he needs confirmation that the destination point got it.
UDP has no inherent order as all packets are independent of each other and he doesn't need any confirmation.
I highly recommend read more about this protocols and determine which type you need before the creation of the script.
Communication implies availability of two points. First one is server, the point which is getting calls and pushing some response. And the second one is an agent, the point which generates these calls to the server. Below is showing examples.
TCP server script
import socket
import threading

bind_ip = "0.0.0.0"
bind_port = 9999

def handle_client(client_socket):
    request = client_socket.recv(1024)

    print("[*] Received: %s" % request)

    client_socket.send("ACK")
    client_socket.close()

if __name__ == "__main__":

    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind((bind_ip,bind_port))
    server.listen(5)

    print("[*] Listening on %s:%d" % (bind_ip,bind_port))

    while True:
        client,addr = server.accept()
        print("[*] Accepted connection from: %s:%d" % (addr[0], addr[1]))
        client_handler = threading.Thread(target=handle_client,args=(client,))
client_handler.start()
TCP client script
import socket

target_host = '127.0.0.1'
target_port = 9999

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((target_host, target_port))
client.send("GET / HTTP/1.1\r\nHost: localhost\r\n\r\n".encode())
response = client.recv(4096).decode()
print(response)
It's a simple examples of these two communicate scripts. If we run them, we will see that the server will accept the connection from client and will send response.
These scripts are very easy understandable, but I want to get your attention to this line : server = socket.socket(socket.AF_INET, socket.SOCK_STREAM).
Exactly this line is set type of our socket.
AF_INET - parameter which told that the socket should using address family (hostname or IP)
SOCK_STREAM - parameter which said that this socket of TCP type
If we are talking about UDP example, principe is stay absolutely the same, need to change only type of socket (from SOCK_STREAM to SOCK_DGRAM )
Example is follow.
UDP server script

import socket
import time

target_host = '0.0.0.0'
target_port = 9999
message = "test message"

server_address = (target_host, target_port)
#socket object
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#connect to client
client.bind(server_address)

print("Awaiting messages from hosts")

while True:
    data, addr = client.recvfrom(1024)
    print ("Received message:", data)
UDP client script

import socket
import time

target_host = 'localhost'
target_port = 9999
message = "test message"

server_address = (target_host, target_port)
#socket object
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#connect to client
client.bind(server_address)
client.settimeout(1)

while True:
    sent = client.sendto(message.encode(), server_address)
    time.sleep(1)
Based on these examples, we can develop personal services and scripts. But also I want to discuss about Websockets in the Python. So, here we go.

WebSockets

Actually, websockets are normal sockets, but with few some differences. Websockets are supporting an HTTP-compatible handshake. This is very cool and comforable for working with browser clients. The HTTP-compatible handshake is allowing websocket connection on the same port that a webserver is running on. And if connection is established, the server is not be on loop state. This is give possibility to skip the limit of browser clients. Let's review an example.
Server with websocket
import socket

def Main():
    host = "0.0.0.0"
    port = 9999

    mySocket = socket.socket()
    mySocket.bind((host,port))

    mySocket.listen(1)
    conn, addr = mySocket.accept()
    print ("Connection from: " + str(addr))
    while True:
            data = conn.recv(1024).decode()
            if not data:
                    break
            print ("from connected  user: " + str(data))

            data = str(data).upper()
            print ("sending: " + str(data))
            conn.send(data.encode())

    conn.close()

if __name__ == '__main__':
    Main()
But instead of simply client, let's write real example of connection via HTTP and JavaScript.
<head>
    <title>Test</title>
    <script src="jquery.js"></script>  
    <script type="application/javascript">
        var ws;

        function init() {
            var servermsg = document.getElementById("servermsg");
            ws = new WebSocket("ws://127.0.0.1:9999/");
            ws.onopen = function(){
                servermsg.innerHTML = servermsg.innerHTML + "<br>Server connected";
            };
            ws.onmessage = function(e){
                servermsg.innerHTML = servermsg.innerHTML + "<br><< Recieved data: " + e.data;
            };
            ws.onclose = function(){
                servermsg.innerHTML = servermsg.innerHTML + "<br>Server disconnected";
            };
        }
        function postmsg(){
            var text = document.getElementById("message").value;
            ws.send(text);
            servermsg.innerHTML = servermsg.innerHTML + "<br>>> Data sent: " + text;
        }


    </script>
</head>
<body onload="init();">
    <form action="" onSubmit="postmsg();return false;">
        <input type="text" name="message" value="" id="message">
        <input type="submit" name="submit" value="" id="submit">
    </form>
    <div id="servermsg"><h1>Message log:</h1></div>
</body>
Try to implement this example on your host and you will see how is communicating your http server with Python websocket.

Conclusion

We reviewed all types of the socket and from this examples, you can develop your own project, but before that carefully investigate goals of your future project and choose correct type.

Resources

And as usual, all these examples you can find on my GitHub profile.

Sockets are very important part of modern IT sphere and I hope that this information was useful and clear. But in any case, if you'll have any questions or will need some help, feel free to contact me. I'll be waiting for your emails.
- Kostia

0 Comments


    Leave a Comment