gpt4 book ai didi

swift - 如何使用Swift查找免费的本地端口?

转载 作者:行者123 更新时间:2023-12-03 12:07:14 24 4
gpt4 key购买 nike

对于本地服务器,我需要指定一个端口,该端口不得使用。有一个非常整洁的solution in Python可以获取一个免费端口。但是,这样的套接字库在Swift中不可用。因此,我尝试了Using BSD Sockets in Swift,但实际上是要预先指定端口,而我无法使bind命令正常工作。这是我尝试的代码:

    let socketFD = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if socketFD == -1 {
print("Error creating BSD Socket")
return
}

var hints = addrinfo(
ai_flags: AI_PASSIVE, // Assign the address of the local host to the socket structures
ai_family: AF_UNSPEC, // Either IPv4 or IPv6
ai_socktype: SOCK_STREAM, // TCP
ai_protocol: 0,
ai_addrlen: 0,
ai_canonname: nil,
ai_addr: nil,
ai_next: nil)

var servinfo: UnsafeMutablePointer<addrinfo>? = nil
let addrInfoResult = getaddrinfo(
nil, // Any interface
"8000", // The port on which will be listenend
&hints, // Protocol configuration as per above
&servinfo);

if addrInfoResult != 0 {
print("Error getting address info: \(errno)")
return
}

let bindResult = Darwin.bind(socketFD, servinfo!.pointee.ai_addr, socklen_t(servinfo!.pointee.ai_addrlen));
if bindResult == -1 {
print("Error binding socket to Address: \(errno)")
return
}

let listenResult = Darwin.listen(socketFD, 1);
if listenResult == -1 {
print("Error setting our socket to listen")
return
}

let port = Darwin.getsockname(socketFD, nil, nil);

bind调用总是返回-1,因为我想获得一个空闲端口,所以在 getaddrinfo中指定一个是没有意义的。这里正确的方法是什么?

最佳答案

这是一个可行的解决方案:

func findFreePort() -> UInt16 {
var port: UInt16 = 8000;

let socketFD = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if socketFD == -1 {
//print("Error creating socket: \(errno)")
return port;
}

var hints = addrinfo(
ai_flags: AI_PASSIVE,
ai_family: AF_INET,
ai_socktype: SOCK_STREAM,
ai_protocol: 0,
ai_addrlen: 0,
ai_canonname: nil,
ai_addr: nil,
ai_next: nil
);

var addressInfo: UnsafeMutablePointer<addrinfo>? = nil;
var result = getaddrinfo(nil, "0", &hints, &addressInfo);
if result != 0 {
//print("Error getting address info: \(errno)")
close(socketFD);

return port;
}

result = Darwin.bind(socketFD, addressInfo!.pointee.ai_addr, socklen_t(addressInfo!.pointee.ai_addrlen));
if result == -1 {
//print("Error binding socket to an address: \(errno)")
close(socketFD);

return port;
}

result = Darwin.listen(socketFD, 1);
if result == -1 {
//print("Error setting socket to listen: \(errno)")
close(socketFD);

return port;
}

var addr_in = sockaddr_in();
addr_in.sin_len = UInt8(MemoryLayout.size(ofValue: addr_in));
addr_in.sin_family = sa_family_t(AF_INET);

var len = socklen_t(addr_in.sin_len);
result = withUnsafeMutablePointer(to: &addr_in, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
return Darwin.getsockname(socketFD, $0, &len);
}
});

if result == 0 {
port = addr_in.sin_port;
}

Darwin.shutdown(socketFD, SHUT_RDWR);
close(socketFD);

return port;
}

关于swift - 如何使用Swift查找免费的本地端口?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65670932/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com