2012-06-13 54 views
6

Tôi trước đây đã sử dụng mã bên dưới để liên kết địa chỉ IPv4 với ổ cắm Python dưới dạng địa chỉ ip nguồn.Ràng buộc địa chỉ IPv6 vào ổ cắm Python làm địa chỉ IP nguồn

import socket 
true_socket = socket.socket 
def bound_socket(*a, **k): 
    sock = true_socket(*a, **k) 
    sock.bind((sourceIP, 0)) 
    return sock 
socket.socket = bound_socket 

Mã trên có hoạt động cho địa chỉ IPv6 không? Nếu không, làm thế nào tôi có thể ràng buộc một địa chỉ IPv6?

Cảm ơn trước!

Trả lời

6

bạn có thể thử này, để có được một địa chỉ IPV6, nó là khuyên bạn nên sử dụng socket.getaddrinfo nó sẽ trở lại tất cả các địa chỉ khác nhau cả IPv4 và IPv6, bạn có thể liên kết tất cả chúng hay chỉ là phương thức nào bạn muốn/nhu cầu.

import socket 
def bound_socket(*a, **k): 
    sock = socket.socket(*a, **k) 
    if socket.AF_INET6 in a: 
     if not socket.has_ipv6: 
      raise ValueError("There's no support for IPV6!") 
     else: 
      address = [addr for addr in socket.getaddrinfo(source_ip, None) 
         if socket.AF_INET6 == addr[0]] # You ussually want the first one. 
      if not address: 
       raise ValueError("Couldn't find ipv6 address for source %s" % source_ip) 
      sock.bind(address[0][-1]) 
    else: 
     sock.bind((source_ip, 0)) 
    return sock 
2

Điều này cần thực hiện thủ thuật ... đặt họ địa chỉ.

import socket 
s = socket.socket(family=socket.AF_INET6) 
s.bind(('::1', 1234)) 
3

Nếu bạn thực sự muốn có một giải pháp mở rộng, bạn có thể mở rộng giải pháp của bạn để sử dụng getaddrinfo():

import socket 
l = socket.getaddrinfo(None, "", 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE) 
for i in l: print i 

Điều này cho phép

(2, 1, 6, '', ('0.0.0.0', 0)) 
(10, 1, 6, '', ('::', 0, 0, 0)) 

Đây là những thông số bạn nên tạo một ổ cắm với :

s = socket.socket(i[0], i[1], i[2]) 
if i[0] == AF_INET6: s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1) 
s.bind(i[4]) 

Bây giờ bạn có nhiều ổ cắm khi bạn có các giao thức và bạn có thể sử dụng chúng. (Than ôi, IPV6_V6ONLY không hoạt động dưới các phiên bản Windows cũ hơn ...)

Nếu bạn có một tên máy chủ cho/IP để ràng buộc vào, làm

l = socket.getaddrinfo("mylocalIP", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE) 

và nó sẽ chọn đúng địa chỉ/gia đình giao thức dành cho bạn:

>>> socket.getaddrinfo("::1", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE) 
[(10, 1, 6, '', ('::1', 0, 0, 0))] 
>>> socket.getaddrinfo("127.0.0.1", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE) 
[(2, 1, 6, '', ('127.0.0.1', 0))] 
>>> socket.getaddrinfo("localhost", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE) 
[(10, 1, 6, '', ('::1', 0, 0, 0)), (2, 1, 6, '', ('127.0.0.1', 0))] 
>>> socket.getaddrinfo("192.168.1.32", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE) 
[(2, 1, 6, '', ('192.168.1.32', 0))] 

, vv

2 vs 10AF_INET vs AF_INET6; socket.AI_PASSIVE có nghĩa là bạn cần địa chỉ này cho bind() ing.

Các vấn đề liên quan