关于端口复用
一个套接字不能同时绑定多个端口,如果客户端想绑定端口号,一定要调用发送信息函数之前绑定( bind )端口,因为在发送信息函数( sendto, 或 write ),系统会自动给当前网络程序分配一个随机端口号,这相当于随机绑定了一个端口号,这里只会分配一次,以后通信就以这个随机端口通信,我们再绑定端口号的话,就会绑定失败。如果我们放在发送信息函数( sendto, 或 write )之前绑定,那样程序将以我们绑定的端口号发送信息,不会再随机分配一个端口号。实际上,默认的情况下,如果一个网络应用程序的一个套接字 绑定了一个端口,这时候,别的套接字就无法使用这个端口。那如何让两个套接字都能成功绑定一个端口呢"htmlcode">
def startServer(queue, port):
reactor.listenUDP(port, DhtResponseHandler(queue))
reactor.run()
def sendUdpMsg(self, addr, msg):
socketHandler = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socketHandler.bind(("", self.port))
socketHandler.sendto(msg, addr)
socketHandler.close()
由于要向同一个端口写数据,于是client必须有bind,但是运行后发现server先bind了这个端口,client运行时会报错
复制代码 代码如下:
error: [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
一般这种错误时因为多个socket不能同时bind同一个地址
由于基础不够扎实,我开始疯狂的搜索,发现有人说端口复用的问题,所谓的端口复用,是指一个套接字释放掉一个端口后有一个wait_time,另一个套接字如果接着bind就会报错。虽然我的问题不完全一样,但是我欣喜若狂的使用了。即在client bind前加上如下一句
socketHandler.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
但是仍然报错:
复制代码 代码如下:
error: [Errno 10013] An attempt was made to access a socket in a way forbidden by its access permissions
(顺便一提,还有另一个参数叫SO_REUSEPORT,即复用端口,另外有一个叫SO_EXCLUSIVEADDRUSE,即不准复用该端口,其他socket的参数还有很多,可以参考winsockhttp://msdn.microsoft.com/en-us/library/aa924071.aspx或者unix下的socket)
这个10013错误让我百思不得其解,搜索一下,主要有两种解释,有人说是需要提升应用程序的权限为管理员,我用的是eclipse+pydev,提升完eclipse权限没用,实际上还要修改python.exe的权限,方法是在这个程序上右键,兼容性一栏中勾上以系统管理员身份运行;有人说是跟其他程序地址或者端口冲突。但是我测试过发现都不行。
另外,运行的时候发现,twisted的服务器端一定是要在主线程中,否则会报signal一定要在主线程才能接受的错误,但是twisted的reactor一运行起来就阻塞了。
在twisted文档中翻到,原来还有一种UDP叫做connected UDP,变态吧,所谓connected UDP,就是只能向一个地址收发数据,看起来貌似可以,但是不符合可以向多个地址接收数据。
最后在一篇文章中翻到说需要两个端口都设置重用,于是我试着重新写一个服务器,与之前的客户端配合,运行良好,完全无错
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("", port))
data, address = sock.recvfrom(4096)
好吧,看来问题在调用twisted了,不知道他是否有这样的设置,进去将这部分代码翻了一下,找不到这样设置的参数。
class Port(abstract.FileHandle):
def __init__(self, port, proto, interface='', maxPacketSize=8192,
reactor=None):
"""
Initialize with a numeric port to listen on.
"""
self.port = port
self.protocol = proto
self.readBufferSize = maxPacketSize
self.interface = interface
self.setLogStr()
self._connectedAddr = None
abstract.FileHandle.__init__(self, reactor)
skt = socket.socket(self.addressFamily, self.socketType)
addrLen = _iocp.maxAddrLen(skt.fileno())
self.addressBuffer = _iocp.AllocateReadBuffer(addrLen)
# WSARecvFrom takes an int
self.addressLengthBuffer = _iocp.AllocateReadBuffer(
struct.calcsize('i'))
def startListening(self):
"""
Create and bind my socket, and begin listening on it.
This is called on unserialization, and must be called after creating a
server to begin listening on the specified port.
"""
self._bindSocket()
self._connectToProtocol()
def createSocket(self):
return self.reactor.createSocket(self.addressFamily, self.socketType)
def _bindSocket(self):
try:
skt = self.createSocket()
skt.bind((self.interface, self.port))
except socket.error, le:
raise error.CannotListenError, (self.interface, self.port, le)
# Make sure that if we listened on port 0, we update that to
# reflect what the OS actually assigned us.
self._realPortNumber = skt.getsockname()[1]
log.msg("%s starting on %s" % (
self._getLogPrefix(self.protocol), self._realPortNumber))
self.connected = True
self.socket = skt
self.getFileHandle = self.socket.fileno
难道说twisted就完全不提供这样的功能?最终在multicast中翻到这样一段,也就是,多播的情况是支持地址复用的,动手测起来。
class MulticastPort(MulticastMixin, Port):
"""
UDP Port that supports multicasting.
"""
implements(interfaces.IMulticastTransport)
def __init__(self, port, proto, interface='', maxPacketSize=8192,
reactor=None, listenMultiple=False):
Port.__init__(self, port, proto, interface, maxPacketSize, reactor)
self.listenMultiple = listenMultiple
def createSocket(self):
skt = Port.createSocket(self)
if self.listenMultiple:
skt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if hasattr(socket, "SO_REUSEPORT"):
skt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
return skt
将server端改成如下代码,运行通过!
reactor.listenMulticast(port, DhtResponseHandler(queue), listenMultiple=True) reactor.run()
感触良多,底层的知识比较重要,浮沙筑高台果然危险。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]