杰瑞科技汇

Python getsockname()如何获取本地地址?

Of course! In Python, you get the socket's own address (the local address it's bound to) using the getsockname() method of a socket object.

Python getsockname()如何获取本地地址?-图1
(图片来源网络,侵删)

This is the counterpart to getpeername(), which gets the address of the remote peer you are connected to.

The Short Answer

For a socket object s, call:

local_address = s.getsockname()

This returns a tuple, typically (ip_address, port). For IPv6, it might also include a flow ID and scope ID.


Detailed Explanation with Examples

Let's break it down with practical examples for both server and client sockets.

Python getsockname()如何获取本地地址?-图2
(图片来源网络,侵删)

For a Server Socket

A server socket binds to a specific address and port to listen for incoming connections. getsockname() is very useful here to confirm that the socket is bound correctly.

Scenario: A simple TCP server that binds to all available network interfaces ('0.0.0.0') on port 65432.

import socket
# Use a context manager to ensure the socket is closed automatically
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # Bind the socket to a specific address and port
    # '0.0.0.0' means listen on all available network interfaces
    HOST = '0.0.0.0'
    PORT = 65432
    s.bind((HOST, PORT))
    # Now that the socket is bound, we can get its name
    local_address = s.getsockname()
    print(f"Server socket bound to: {local_address}")
    s.listen()
    print("Server is listening for connections...")
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        # ... server logic here ...

Output:

Server socket bound to: ('0.0.0.0', 65432)
Server is listening for connections...

Notice that the address is the one we specified in s.bind().


For a Client Socket

A client socket typically doesn't bind to a specific address and port; the operating system assigns it an available ephemeral (temporary) port when you call connect().

Scenario: A simple TCP client that connects to the server from the previous example.

import socket
HOST = '127.0.0.1'  # The server's IP address (localhost)
PORT = 65432        # The port the server is listening on
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # Connect to the server
    s.connect((HOST, PORT))
    # After connecting, the OS has assigned a local port
    local_address = s.getsockname()
    print(f"Client socket's local address: {local_address}")
    # Get the address of the server we connected to
    peer_address = s.getpeername()
    print(f"Connected to server at: {peer_address}")
    # ... send and receive data ...

Sample Output (the port number will likely be different each time):

Client socket's local address: ('127.0.0.1', 54321)  # 54321 is an example ephemeral port
Connected to server at: ('127.0.0.1', 65432)

Here, getsockname() reveals the client's own assigned IP and port, while getpeername() shows the server's address.


Key Differences: getsockname() vs. getpeername()

This is a common point of confusion. Here’s a simple table to clarify:

Method What it Returns When it's Useful Example Return Value
getsockname() The local address of the socket. To confirm where your socket is bound or what port the OS assigned it. ('127.0.0.1', 54321)
getpeername() The remote address of the connected peer. To find out who you are connected to (after a successful accept() or connect()). ('127.0.0.1', 65432)

Important Note: You can only call getpeername() on a connected socket. For a server, this means after s.accept(). For a client, this means after s.connect(). Calling it on an unconnected socket will raise an error.


Handling Errors

You might encounter an OSError if you call getsockname() at the wrong time.

  • OSError: [Errno 22] Invalid argument: This often happens if you call getsockname() on a socket that has not yet been bound. A socket is not "named" until it's bound to an address.
  • OSError: [Errno 107] Transport endpoint is not connected: This happens with getpeername() if the socket is not connected to a peer.

Example: IPv6

The same principles apply to IPv6. The address format will just be different.

import socket
# Create an IPv6 socket
with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
    # Bind to all IPv6 interfaces
    s.bind(('::', 12345))
    local_address = s.getsockname()
    print(f"IPv6 Server bound to: {local_address}")
    # Output might look like:
    # IPv6 Server bound to: ('::', 12345, 0, 0)
    # The last two numbers are the flow and scope ID.

Summary

  • Use socket.getsockname() to find your own socket's address.
  • Call it after the socket has been bind() (for servers) or connect() (for clients).
  • It returns a tuple like (ip, port).
  • It's different from getpeername(), which tells you who you're connected to.
分享:
扫描分享到社交APP
上一篇
下一篇