26/02/2024
GV: Nguyễn Thị Thanh Vân - CNTT
socket() socket()
bind() bind()
recvfrom() sendto()
[blocked] recvfrom()
[blocked]
sendto()
SERVER CLIENT
1
26/02/2024
socket() Server Client
bind()
socket()
listen()
connect()
accept()
write()
[blocked]
read()
read() [blocked]
[blocked]
write()
When interaction is over, server
loops to accept a new connection
Passive participant Active participant
o step 1: listen (for o step 2: request & establish
incoming requests) connection
o step 3: accept (a request)
o step 4: data transfer o step 4: data transfer
Passive Participant
The accepted
connection is on a new a-sock-1 l-sock a-sock-2
socket
The old socket
continues to listen for
other active participants socket socket
Active 1 Active 2
4
2
26/02/2024
Python's socket module has
o class-based utilities – SocketServer module
o instances-based utilities – Socket Object
Socket lib
o from socket import socket
Family address
Socket Types
Server Libraries
3
26/02/2024
Term Term & Description
domain The family of protocols that is used as the transport mechanism. These values
are constants such as AF_INET, PF_INET, PF_UNIX, PF_X25, and so on.
type The type of communications between the two endpoints, typically
SOCK_STREAM for connection-oriented protocols and SOCK_DGRAM for
connectionless protocols.
protocol Typically zero, this may be used to identify a variant of a protocol within a
domain and type.
hostname The identifier of a network interface −
•A string, which can be a host name, a dotted-quad address, or an IPV6 address
in colon (and possibly dot) notation
•A string "<broadcast>", which specifies an INADDR_BROADCAST address.
•A zero-length string, which specifies INADDR_ANY, or
•An Integer, interpreted as a binary address in host byte order.
port Each server listens for clients calling on one or more ports. A port may be a
Fixnum port number, a string containing a port number, or the name of a
service.
Address Families Socket Types
socket.AF_UNIX socket.SOCK_STREAM
o Unix named pipe (NOT o TCP, connection-oriented
Windows…) socket.SOCK_DGRAM
socket.AF_INET o UDP, connectionless
o Internet – IP version 4 socket.SOCK_RAW
o The basis of this class
o Gives access to subnetwork layer
socket.AF_INET6
SOCK_RDM,
o Internet – IP version 6 SOCK_SEQPACKET
o Rather more complicated … o Very rarely used
4
26/02/2024
Can set a default for all sockets
o socket.setdefaulttimeout(seconds)
o Argument is float # of seconds
o Or None (indicates no timeout)
Can set a timeout on an existing socket s
o s.settimeout(seconds)
To create a socket, you must use the socket.socket() function
available in the socket module, which has the general syntax −
s=socket.socket (socket_family, socket_type, protocol = 0)
The description of the parameters −
o socket_family − AF_UNIX or AF_INET,
o socket_type − SOCK_STREAM or SOCK_DGRAM.
o protocol − This is usually left out, defaulting to 0.
Once you have socket object, then you can use the required
functions to create your client or server program. Following is the
list of functions required
5
26/02/2024
S = socket.socket (socket_family, socket_type, protocol = 0)
Method Description
Server Socket
s.bind() This method binds address (hostname, port number
pair) to socket.
s.listen() This method sets up and start TCP listener.
s.accept() This passively accept TCP client connection, waiting
until connection arrives (blocking).
Client Socket
s.connect() This method actively initiates TCP server connection.
Method Description
s.recv() This method receives TCP message
s.send() This method transmits TCP message
s.recvfrom() This method receives UDP message
s.sendto() This method transmits UDP message
s.close() This method closes socket
socket.gethostname() Returns the hostname.
6
26/02/2024
from socket import socket, AF_INET, SOCK_DGRAM
s = socket(AF_INET, SOCK_DGRAM)
s.bind(('127.0.0.1', 11111))
while True:
data, addr = s.recvfrom(1024) Empty -> all
print "Connection from", addr
s.sendto(data.upper(), addr)
Note that the bind() argument is a two-element tuple of address and port
number.
Server can reply multi request from client
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
from socket import socket, AF_INET, SOCK_DGRAM
s = socket(AF_INET, SOCK_DGRAM)
s.bind(('127.0.0.1', 0)) # OS chooses port
print "using", s.getsocketname()
server = ('127.0.0.1', 11111)
s.sendto("MixedCaseString", server)
data, addr = s.recvfrom(1024)
print "received", data, "from", addr
s.close()
7
26/02/2024
from socket import socket, AF_INET, SOCK_STREAM
BUFFER_SIZE = 30 # Normally 1024, but we want fast response
s = socket(AF_INET, SOCK_STREAM) # Create TCP socket
s.bind(("",8888)) # Bind to port 8888
s.listen(5) # Start listening
print ("Server is listening")
conn, addr =s.accept()
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print ("received data:", data)
conn.send(data.upper()) # echo
conn.close()
from socket import *
BUFFER_SIZE = 1024
s = socket(AF_INET,SOCK_STREAM) # Create TCP socket
s.connect(("127.0.0.1",8888)) # Connect to server
print ("Hello, I am using", s.getsockname())
while 1:
msg = input('Enter message to send : ')
s.send(msg.encode('utf-8'))
data = s.recv(BUFFER_SIZE)
print ("received data:", data, "from server ")
if msg == 'Q':
print("Quit now...")
break
s.close()
ConnectionRefusedError: [WinError 10061] No connection could
be made because the target machine actively refused it
8
26/02/2024
SocketServer: A framework for network servers.
Provides:
o Subclass the TCPServer to serve TCP
class socketserver.TCPServer(server_address, RequestHandlerClass
, bind_and_activate=True)
o Subclass the UDPServer to serve UDP
class socketserver.UDPServer(server_address, RequestHandlerClass
, bind_and_activate=True)
In Unix domain sockets:
class socketserver.UnixStreamServer(server_address, RequestHandl
erClass, bind_and_activate=True)
class socketserver.UnixDatagramServer(server_address, RequestHan
dlerClass, bind_and_activate=True)
Creating a server requires several steps:
o 1. create a request handler class by subclassing
the BaseRequestHandler class and overriding its handle() method;
this method will process incoming requests.
o 2. instantiate one of the server classes, passing it the server’s
address and the request handler class.
o 3. call the handle_request() or serve_forever() method of the
server object to process one or many requests.
9
26/02/2024
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# Create the server, binding to localhost on port 9999
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
# keep running until interrupting the program
server.serve_forever()
class MyTCPHandler(socketserver.StreamRequestHandler):
def handle(self):
self.data = self.rfile.readline().strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
self.wfile.write(self.data.upper())
import socket
import sys
HOST, PORT = "localhost", 9999
while 1:
#data = " ".join(sys.argv[1:])
data = input('Enter message to send : ')
# Create a socket (SOCK_STREAM means a TCP socket)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
# Connect to server and send data
sock.connect((HOST, PORT))
sock.sendall(bytes(data + "\n", "utf-8"))
# Receive data from the server and shut down
received = str(sock.recv(1024), "utf-8")
print("Sent: {}".format(data))
print("Received: {}".format(received))
if data == 'Q':
print("Quit now...")
break
10
26/02/2024
Mix-in classes allow asynchronous handling via Two class:
o class socketserver.ForkingMixIn
o class socketserver.ThreadingMixIn
add the ability to handle each request in a separate thread or
a separate process
Serverinstance created with address and handler-class as
arguments:
SocketServer.UDPServer(myaddr, MyHandler)
Each connection/transmission creates a request handler instance
by calling the handler-class*
Created handler instance handles a message (UDP) or a
complete client session (TCP)
* In Python you instantiate a class by calling it like a function
11
26/02/2024
There are two different kind of threads −
o kernel thread
o user thread
Kernel Threads are a part of the operating system, while the User-space
threads are not implemented in the kernel.
There are two modules which support the usage of threads in
Python3
o _thread
o threading
The thread module has been "deprecated" for quite a long time.
Tospawn another thread, you need to call following method
available in _thread module:
_thread.start_new_thread(function, args[, kwargs])
This method call enables a fast and efficient way to create new
threads in both Linux and Windows.
The method call returns immediately and the child thread starts
and calls function with the passed list of args. When function
returns, the thread terminates.
Here, args is a tuple of arguments; use an empty tuple to call
function without passing any arguments. kwargs is an optional
dictionary of keyword arguments.
12
26/02/2024
import _thread
import time
# Define a function for the thread
def print_time( threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print ("%s: %s" % ( threadName, time.ctime(time.time()) ))
# Create two threads as follows
try:
_thread.start_new_thread( print_time, ("Thread-1", 2, ) )
_thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
print ("Error: unable to start thread")
while 1:
pass
Thread-1: Mon Oct 1 11:46:06 2018
Thread-2: Mon Oct 1 11:46:08 2018
Thread-1: Mon Oct 1 11:46:08 2018
Thread-1: Mon Oct 1 11:46:10 2018
Thread-2: Mon Oct 1 11:46:12 2018
Thread-1: Mon Oct 1 11:46:12 2018
Thread-1: Mon Oct 1 11:46:14 2018
Thread-2: Mon Oct 1 11:46:16 2018
Thread-2: Mon Oct 1 11:46:20 2018
Thread-2: Mon Oct 1 11:46:24 2018
Although it is very effective for low-level threading, but the thread
module is very limited compared to the newer threading module.
13
26/02/2024
A thread remains inactive until start method runs
o Thread is placed in the ready queue
o Newly started thread’s run method is also activated
A thread can lose access to the CPU:
o Time-out (process also known as time slicing)
o Sleep
o Block
o Wait
Process of saving/restoring a thread’s state is
called a context switch
14
26/02/2024
Thethreading module exposes all the methods of the thread
module and provides some additional methods:
o threading.activeCount():
Returns the number of thread objects that are active.
o threading.currentThread():
Returns the number of thread objects in the caller's thread control.
o threading.enumerate():
Returns a list of all thread objects that are currently active.
The threading module has the Thread class that implements
threading.
The methods provided by the Thread class are as follows:
o run(): The run() method is the entry point for a thread.
o start(): The start() method starts a thread by calling the run method.
o join([time]): The join() waits for threads to terminate.
o isAlive(): The isAlive() method checks whether a thread is still executing.
o getName(): The getName() method returns the name of a thread.
o setName(): The setName() method sets the name of a thread.
15
26/02/2024
To implement a new thread using the threading module, you have
to do the following −
o Define a new subclass of the Thread class.
o Override the __init__(self [,args]) method to add additional arguments.
o Then, override the run(self [,args]) method to implement what the thread
should do when started.
Operation:
o Once you have created the new Thread subclass, you can create an
instance of it
o Then start a new thread by invoking the start(), which in turn calls run()
method.
import threading Module threading provides multithreading capabilities
import time
Thread class derived from base class threading.Thread
exitFlag = 0
class myThread (threading.Thread): Instantiate PrintThread object
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
# Create new threads
self.threadID = threadID thd1 = myThread(1, "Thread-1", 1)
self.name = name thd2 = myThread(2, "Thread-2", 2)
self.counter = counter # Start new Threads
def run(self): Overridden Thread run method
thd1.start()
print ("Starting " + self.name) thd2.start()
print_time(self.name, self.counter, 5) thd1.join()
print ("Exiting " + self.name) thd2.join()
print ("Exiting Main Thread")
def print_time(threadName, delay, counter):
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
print ("%s: %s" % (threadName, time.ctime(time.time())))
counter -= 1
16
26/02/2024
Starting Thread-1
Starting Thread-2
Thread-1: Mon Oct 1 15:02:36 2018
Thread-2: Mon Oct 1 15:02:37 2018
Thread-1: Mon Oct 1 15:02:37 2018
Thread-1: Mon Oct 1 15:02:38 2018
Thread-2: Mon Oct 1 15:02:39 2018
Thread-1: Mon Oct 1 15:02:39 2018
Thread-1: Mon Oct 1 15:02:40 2018
Exiting Thread-1
Thread-2: Mon Oct 1 15:02:41 2018
Thread-2: Mon Oct 1 15:02:43 2018
Thread-2: Mon Oct 1 15:02:45 2018
Exiting Thread-2
Exiting Main Thread
# Create new threads array
numThr = 3
print('Creating ', numThr, 'threads \n')
worker = list()
for i in range(numThr):
n="Thread_" + str(i)
worker.append(myThread(i, n, i))
worker[i].start()
worker[i].join()
print('Threads have been created and started \n')
17
26/02/2024
Mỗi Thread tạo ra đều thực thi các tác vụ giống nhau (theo run())
Muốn mỗi Thread thực hiện một tác vụ khác nhau?
o Tạo các method riêng cho các thread
o Tạo constructor, giá trị truyền vào khác nhau
o Tạo các thread ở các class khác nhau, viết run() riêng cho mỗi thread.
35
MultiThreads:
Các tuyến đoạn có thể truy xuất tới tài
nguyên dùng chung để cùng làm việc
hợp tác với nhau.
Nảy sinh vấn đề gì?
36
18
26/02/2024
The single expression can be
o Retrieve the current value of c.
o Increment the retrieved value by 1.
o Store the incremented value back in c.
Ex, Thread A invokes increment at about the same
time Thread B invokes decrement. If the initial value of
c is 0,
o Thread A: Retrieve c.
o Thread B: Retrieve c.
o Thread A: Increment retrieved value; result is 1.
o Thread B: Decrement retrieved value; result is -1.
o Thread A: Store result in c; c is now 1.
37
o Thread B: Store result in c; c is now -1.
The threading module provided with Python includes a simple-to-
implement locking mechanism that allows you to synchronize
threads.
A new lock is created by calling the Lock() method, which returns
the new lock.
The acquire(blocking) method of the new lock object is used to
force threads to run synchronously.
o The optional blocking parameter enables you to control whether the
thread waits to acquire the lock.
19
26/02/2024
If blocking is set to 0, the thread returns immediately with a 0
value if the lock cannot be acquired and with a 1 if the lock was
acquired.
If blocking is set to 1, the thread blocks and wait for the lock to be
released.
The release() method of the new lock object is used to release the
lock when it is no longer required.
import threading
import time
class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print ("Starting " + self.name)
# Get lock to synchronize threads
threadLock.acquire()
print_time(self.name, self.counter, 3)
# Free lock to release next thread
threadLock.release()
def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print ("%s: %s" % (threadName, time.ctime(time.time())))
counter -= 1
20
26/02/2024
threadLock = threading.Lock()
threads = []
# Create new threads
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# Start new Threads
thread1.start()
thread2.start()
# Add threads to thread list
threads.append(thread1)
threads.append(thread2)
# Wait for all threads to complete
for t in threads:
t.join()
print ("Exiting Main Thread")
Starting Thread-1
Starting Thread-2
Thread-1: Mon Oct 1 15:30:55 2018
Thread-1: Mon Oct 1 15:30:56 2018
Thread-1: Mon Oct 1 15:30:57 2018
Thread-2: Mon Oct 1 15:30:59 2018
Thread-2: Mon Oct 1 15:31:01 2018
Thread-2: Mon Oct 1 15:31:03 2018
Exiting Main Thread
21
26/02/2024
Socket
Multithread
22