def write(self, datagram, addr=None):
"""
Write a datagram.
@type datagram: L{bytes}
@param datagram: The datagram to be sent.
@type addr: L{tuple} containing L{str} as first element and L{int} as
second element, or L{None}
@param addr: A tuple of (I{stringified IPv4 or IPv6 address},
I{integer port number}); can be L{None} in connected mode.
"""
if self._connectedAddr:
assert addr in (None, self._connectedAddr)
try:
return self.socket.send(datagram)
except socket.error as se:
no = se.args[0]
if no == EINTR:
return self.write(datagram)
elif no == EMSGSIZE:
raise error.MessageLengthError("message too long")
elif no == ECONNREFUSED:
self.protocol.connectionRefused()
else:
raise
else:
assert addr != None
if (not abstract.isIPAddress(addr[0])
and not abstract.isIPv6Address(addr[0])
and addr[0] != "<broadcast>"):
raise error.InvalidAddressError(
addr[0],
"write() only accepts IP addresses, not hostnames")
if ((abstract.isIPAddress(addr[0]) or addr[0] == "<broadcast>")
and self.addressFamily == socket.AF_INET6):
raise error.InvalidAddressError(
addr[0],
"IPv6 port write() called with IPv4 or broadcast address")
if (abstract.isIPv6Address(addr[0])
and self.addressFamily == socket.AF_INET):
raise error.InvalidAddressError(
addr[0], "IPv4 port write() called with IPv6 address")
try:
return self.socket.sendto(datagram, addr)
except socket.error as se:
no = se.args[0]
if no == EINTR:
return self.write(datagram, addr)
elif no == EMSGSIZE:
raise error.MessageLengthError("message too long")
elif no == ECONNREFUSED:
# in non-connected UDP ECONNREFUSED is platform dependent, I
# think and the info is not necessarily useful. Nevertheless
# maybe we should call connectionRefused? XXX
return
else:
raise
评论列表
文章目录