Introduction to the Python Socket Module

Introduction

The socket module in Python provides a low-level network interface, allowing socket communication between different computers over a network. The socket implementation in Python adheres to the BSD (Berkeley Software Distribution) socket standard.

Establishing Network Communication Using the Socket Module

Creating an Object

To create a socket object, you can use the methods of the socket object to establish a connection. The prototype of the socket() function is as follows.

socket( family, type, proto) 

The parameters are defined as follows.

  • family: Address family, optional parameter. Defaults to AF_INET, can also be AF_INET6 or AF_UNIX.
  • type: Socket type, optional parameter. Defaults to SOCK_STREAM.
  • proto: Protocol type, optional parameter.

Binding the Object

You can bind an IP address and port using the bind method of the socket object. The prototype of the bind method is as follows.

bind(address) 

The parameters are defined as follows.

  • address: A tuple consisting of an IP address and port, such as (‘127.0.0.1’, 1051). If the IP address is empty, it refers to the local machine.

Listening for Connections

You can listen for connections created by the socket object using the listen method. The function prototype is as follows.

listen(backlog) 
  • The parameters are defined as follows. backlog: Specifies the number of connections in the queue, with a minimum value of 1. The maximum value is determined by the operating system, generally around 5.

Connecting to the Server

You can connect to the server using the connect and connect_ex methods of the socket object. The difference is that connect returns an error if the connection fails, while connect_ex raises an exception. The function prototypes are as follows.

connect(address) 
connect_ex(address) 

The parameters are the same, as shown below.

  • address: A tuple consisting of an IP address and port.

Accepting Connections from Clients

You can accept connections from clients using the accept method of the socket object. The accept method returns a new socket object and the address of the client. You can use the recv and recvfrom methods of the socket object to receive data. The difference is that recvfrom returns the received string and address, while recv only returns the string. The prototypes are as follows.

recv(bufsize, flags) 
recvfrom(bufsize, flags) 

The parameters are the same, as shown below.

  • bufsize: Specifies the size of the receive buffer.
  • flags: Receive flags, optional parameter.

Sending Data

You can send data to an already connected socket using the send and sendall methods of the socket object. The difference is that sendall sends all data at once. The prototypes are as follows.

send(string, flags) 
sendall(string, flags) 

The parameters are the same, as shown below.

  • string: The data to be sent.
  • flags: Send flags, optional parameter.

Sending Data from an Unconnected Socket

You can send data to an unconnected socket using the sendto method of the socket object. The parameter prototype is as follows.

sendto(string, flags, address) 

The parameters are defined as follows.

  • string: The data to be sent.
  • flags: Send flags, optional parameter.
  • address: A tuple consisting of an IP address and port.

Associating with a File Object

You can associate a socket with a file object using the makefile method of the socket object. The prototype is as follows.

makefile(mode, bufsize) 

The parameters are defined as follows.

  • mode: File mode, optional parameter.
  • bufsize: Buffer size, optional parameter.

Closing the Connection

After communication is complete, you should close the network connection using the close method of the socket object.

Example

Sending Data

Server Program

#-*- coding:utf-8 -*- 
#file: server.py 
#
import tkinter 
import threading 
import socket 

class ListenThread(threading.Thread):                   # Listening thread 
    def __init__(self,edit,server):
        threading.Thread.__init__(self) 
        self.edit = edit                                # Save the multi-line text box in the window 
        self.server = server 
    def run(self):                                      # Enter listening state 
        while True:                                    # Use while loop to wait for connection 
            try:                                        # Capture exceptions 
                client, addr = self.server.accept()     # Wait for connection 
                self.edit.insert(tkinter.END,           # Output status to text box 
                        'Connection from: %s:%d\n' % addr) 
                data = client.recv(1024)                # Receive data 
                self.edit.insert(tkinter.END,           # Output data to text box 
                        'Received data: %s \n' % data) 
                client.send(str('I GOT: %s' % data).encode())   # Send data 
                client.close()                          # Close connection with client 
                self.edit.insert(tkinter.END,           # Output status to text box 
                        'Client closed\n') 
            except:                                     # Exception handling 
                self.edit.insert(tkinter.END,           # Output status to text box 
                        'Connection closed\n') 
                break                                   # End loop 

class Control(threading.Thread):                        # Control thread 
    def __init__(self, edit):
        threading.Thread.__init__(self) 
        self.edit = edit                                # Save the multi-line text box in the window 
        self.event = threading.Event()                  # Create Event object 
        self.event.clear()                              # Clear event flag 
    def run(self):
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)                                                                      # Create socket connection 
        server.bind(('', 1051))                         # Bind local port 1051 
        server.listen(1)                                # Start listening 
        self.edit.insert(tkinter.END,'Waiting for connection\n')    # Output status to text box 
        self.lt = ListenThread(self.edit,server)        # Create listening thread object 
        self.lt.setDaemon(True) 
        self.lt.start()                                 # Execute listening thread 
        self.event.wait()                               # Enter waiting state 
        server.close()                                  # Close connection 
    def stop(self):                                     # End control process 
        self.event.set()                                # Set event flag 

class Window:                                           # Main window 
    def __init__(self, root):
        self.root = root 
        self.butlisten = tkinter.Button(root,           # Create component 
                text = 'Start Listening', command = self.Listen) 
        self.butlisten.place(x = 20, y = 15) 
        self.butclose = tkinter.Button(root, 
                text = 'Stop Listening', command = self.Close) 
        self.butclose.place(x = 120, y = 15) 
        self.edit = tkinter.Text(root) 
        self.edit.place(y = 50) 
    def Listen(self):                                   # Handle button event 
        self.ctrl = Control(self.edit)                  # Create control thread object 
        self.ctrl.setDaemon(True) 
        self.ctrl.start()                               # Execute control thread 
    def Close(self):
        self.ctrl.stop()                                # End control thread 
root = tkinter.Tk() 
window = Window(root) 
root.mainloop() 

Client Program

#-*- coding:utf-8 -*- 
#file: client.py 
#
import tkinter 
import socket 
class Window:
    def __init__(self, root):                               # Create component 
        label1 = tkinter.Label(root, text = 'IP') 
        label2 = tkinter.Label(root, text = 'Port') 
        label3 = tkinter.Label(root, text = 'Data') 
        label1.place(x = 5, y = 5) 
        label2.place(x = 5, y = 30) 
        label3.place(x = 5, y = 55) 
        self.entryIP = tkinter.Entry(root) 
        self.entryIP.insert(tkinter.END, '127.0.0.1') 
        self.entryPort = tkinter.Entry(root) 
        self.entryPort.insert(tkinter.END, '1051') 
        self.entryData = tkinter.Entry(root) 
        self.entryData.insert(tkinter.END, 'Hello') 
        self.Recv = tkinter.Text(root) 
        self.entryIP.place(x = 40, y = 5) 
        self.entryPort.place(x = 40, y = 30) 
        self.entryData.place(x = 40, y = 55) 
        self.Recv.place(y = 115) 
        self.send = tkinter.Button(root, text = 'Send Data', command = self.Send) 
        self.send.place(x = 40, y = 80) 
    def Send(self):                                         # Button event 
        try:                                                # Exception handling 
            ip = self.entryIP.get()                         # Get IP 
            port = int(self.entryPort.get())                # Get port 
            data = self.entryData.get()                     # Get data to send 
            client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)                                                                      # Create socket object 
            client.connect((ip,port))                       # Connect to server 
            client.send(data.encode())                               # Send data 
            rdata = client.recv(1024)                       # Receive data 
            self.Recv.insert(tkinter.END, 'Server: ' + rdata.decode() + '\n')                                                               # Output received data 
            client.close()                                  # Close connection 
        except : 
            self.Recv.insert(tkinter.END, 'Send Error\n') 
root = tkinter.Tk() 
window = Window(root) 
root.mainloop() 

Transferring Files

Server Program

#-*- coding:utf-8 -*- 
#file: FileServer.py 
#
import tkinter 
import threading 
import socket 
import os 
class ListenThread(threading.Thread):                   # Create listening thread 
    def __init__(self,edit,server):
        threading.Thread.__init__(self) 
        self.edit = edit                                # Save the multi-line text box in the window 
        self.server = server 
        self.file = 'receive.txt'
    def run(self):                                      # Enter listening state 
        while True:                                    # Use while loop to continuously listen 
            try:                                        # Capture exceptions 
                self.client, addr = self.server.accept()    # Wait for connection 
                self.edit.insert(tkinter.END,           # Output status to text box 
                        'Connection from: %s:%d\n' % addr) 
                self.edit.insert(tkinter.END,           # Output data to text box 
                        'Starting to receive data:') 
                file = os.open(self.file, os.O_WRONLY|os.O_CREAT    # Create file 
                        |os.O_EXCL|os.O_BINARY) 
                while True: 
                    rdata = self.client.recv(1024)      # Receive data 
                    if not rdata: 
                        break
                    os.write(file,rdata)                # Write data to file 
                    self.edit.insert(tkinter.END,'......') # Output progress to text box 
                os.close(file)                          # Close file 
                self.client.close()                     # Close connection with client 
                self.edit.insert(tkinter.END,           # Output status to text box 
                        '\nReceiving complete, closing client\n') 
            except:                                     # Exception handling 
                self.edit.insert(tkinter.END,           # Output status to text box 
                        '\nNetwork error, closing connection\n') 
                break                                   # End loop 

class Control(threading.Thread):                        # Control thread 
    def __init__(self, edit):
        threading.Thread.__init__(self) 
        self.edit = edit                                # Save the multi-line text box in the window 
        self.event = threading.Event()                  # Create Event object 
        self.event.clear()                              # Clear event flag 
    def run(self):
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)      # Create socket connection 
        server.bind(('', 1051))                         # Bind local port 1051 
        server.listen(1)                                # Start listening 
        self.edit.insert(tkinter.END,'Waiting for connection\n')    # Output status to text box 
        self.lt = ListenThread(self.edit,server)        # Create listening thread object 
        self.lt.setDaemon(True) 
        self.lt.start()                                 # Execute listening thread 
        self.event.wait()                               # Enter waiting state 
        server.close()                                  # Close connection 
    def stop(self):                                     # End control process 
        self.event.set()                                # Set event flag 

class Window:                                           # Main window 
    def __init__(self, root):
        self.root = root 
        self.butlisten = tkinter.Button(root,           # Create component 
                text = 'Start Listening', command = self.Listen) 
        self.butlisten.place(x = 20, y = 15) 
        self.butclose = tkinter.Button(root, 
                text = 'Stop Listening', command = self.Close) 
        self.butclose.place(x = 120, y = 15) 
        self.edit = tkinter.Text(root) 
        self.edit.place(y = 50) 
    def Listen(self):                                   # Handle button event 
        self.ctrl = Control(self.edit)                  # Create control thread object 
        self.ctrl.setDaemon(True) 
        self.ctrl.start()                               # Execute control thread 
    def Close(self):
        self.ctrl.stop()                                # End control thread 
root = tkinter.Tk() 
window = Window(root) 
root.mainloop() 

Client Program

#-*- coding:utf-8 -*- 
#file: FileClient.py 
#
import tkinter 
import tkinter.filedialog 
import socket 
import os 
class Window:
    def __init__(self, root):                           # Create component 
        label1 = tkinter.Label(root, text = 'IP') 
        label2 = tkinter.Label(root, text = 'Port') 
        label3 = tkinter.Label(root, text = 'File') 
        label1.place(x = 5, y = 5) 
        label2.place(x = 5, y = 30) 
        label3.place(x = 5, y = 55) 
        self.entryIP = tkinter.Entry(root) 
        self.entryIP.insert(tkinter.END, '127.0.0.1') 
        self.entryPort = tkinter.Entry(root) 
        self.entryPort.insert(tkinter.END, '1051') 
        self.entryData = tkinter.Entry(root) 
        self.entryData.insert(tkinter.END, 'Hello') 
        self.entryIP.place(x = 40, y = 5) 
        self.entryPort.place(x = 40, y = 30) 
        self.entryData.place(x = 40, y = 55) 
        self.send = tkinter.Button(root, text = 'Send File', command = self.Send) 
        self.openfile = tkinter.Button(root, text = 'Browse', command = self.Openfile) 
        self.send.place(x = 40, y = 80) 
        self.openfile.place( x = 170, y = 55) 
    def Send(self):                                     # Button event 
        try:                                            # Exception handling 
            ip = self.entryIP.get()                     # Get IP 
            port = int(self.entryPort.get())            # Get port 
            filename = self.entryData.get()             # Get file to send 
            tt = filename.split('/') 
            name = tt[len(tt)-1] 
            client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)            # Create socket object 
            client.connect((ip,port))                   # Connect to server 
            client.send(name.encode())                  # Send filename 
            file = os.open(filename, os.O_RDONLY | os.O_EXCL|os.O_BINARY)                        # Open file 
            while True:                                    # Send file 
                data = os.read(file,1024) 
                if not data: 
                    break
                client.send(data) 
            os.close(file)                              # Close file 
            client.close()                              # Close connection 
        except Exception as e : 
            print('Send Error',e) 
    def Openfile(self):
        r = tkinter.filedialog.askopenfilename(title = 'Python tkinter',    # Create open file dialog 
            filetypes=[('All files', '*'),('Python', '*.py *.pyw')]) 
        if r: 
            self.entryData.delete(0, tkinter.END) 
            self.entryData.insert(tkinter.END, r) 
        
root = tkinter.Tk() 
window = Window(root) 
root.mainloop() 

Leave a Comment