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()