[파이썬] socket 블로킹하지 않는 소켓

In network programming, a socket is an endpoint for sending and receiving data across a computer network. By default, socket operations are blocking, which means that the program execution will pause until the requested operation completes. However, in certain scenarios, non-blocking sockets can be more efficient and provide better performance.

In this blog post, we will explore how to create and use non-blocking sockets in Python, allowing for concurrent operations without blocking the program execution.

Understanding Blocking and Non-blocking Sockets

In traditional blocking sockets, when a program makes a socket call (such as send() or recv()), it waits until the operation is complete or until a timeout occurs. This behavior can lead to performance issues in situations where multiple sockets need to be managed simultaneously.

On the other hand, non-blocking sockets allow for non-blocking I/O operations. When a program makes a non-blocking socket call, it immediately returns control to the program, regardless of whether the operation is complete or not. This enables the program to continue executing other tasks, making it more responsive and versatile.

Using the select Module

Python provides the select module to work with non-blocking sockets. This module allows us to monitor multiple sockets simultaneously and determine which ones are ready for reading, writing, or have encountered an error.

Here is a simple example that demonstrates the usage of non-blocking sockets with the select module:

import socket
import select

# Create a non-blocking socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setblocking(0)

# Bind and listen to a specific address and port
server_socket.bind(('127.0.0.1', 8080))
server_socket.listen(5)

# Create a list to hold client sockets
client_sockets = []

while True:
    # Use the select module to monitor sockets
    readable, _, _ = select.select([server_socket] + client_sockets, [], [])

    for sock in readable:
        if sock is server_socket:
            # Accept new client connections
            client_socket, address = server_socket.accept()
            client_socket.setblocking(0)
            client_sockets.append(client_socket)
        else:
            # Handle data from connected clients
            data = sock.recv(1024)
            if data:
                # Process the received data
                # ...
            else:
                # Remove disconnected clients
                sock.close()
                client_sockets.remove(sock)

In the above example, we create a non-blocking server socket and set it to listen for incoming connections. By using the select module, we can monitor both the server socket and connected client sockets for any available data to read.

Benefits of Non-blocking Sockets

Using non-blocking sockets can provide several benefits, including:

  1. Concurrent operations: Non-blocking sockets allow for concurrent read and write operations on multiple sockets, enabling efficient communication with several clients simultaneously.

  2. Responsive programs: With non-blocking sockets, the program can continue executing other tasks while waiting for I/O operations to complete. This prevents the program from becoming unresponsive or hanging indefinitely.

  3. Timeout control: By specifying timeout values when using the select module, we can control the duration for which the program waits for I/O operations to complete. This helps in managing resources effectively.

Conclusion

Non-blocking sockets are a powerful tool in network programming, especially when dealing with multiple connections concurrently. Python provides the select module to work with non-blocking sockets, allowing for efficient I/O operations and responsive program execution. By incorporating non-blocking sockets into your networking applications, you can improve performance and scalability.

Remember to handle possible errors and exceptions when working with non-blocking sockets, and make use of available resources such as multi-threading or asynchronous programming libraries to further enhance the capabilities of your application.