有人能告诉我如何在Swift2中发现端口是否忙碌吗?因为我写了一个mac应用程序,它有一个自己写的Tcp服务器,但有时它不会启动,因为它“* 无法绑定到端口 *"。那么,我如何才能检查如果端口没有使用,阻止Tcp服务器的启动按钮,直到端口是空闲的,再次?我不想要一个新的框架。谢谢
lpwwtiir1#
主要代码取自Swifter:https://github.com/glock45/swifter
func checkTcpPortForListen(port: in_port_t) -> (Bool, descr: String){ let socketFileDescriptor = socket(AF_INET, SOCK_STREAM, 0) if socketFileDescriptor == -1 { return (false, "SocketCreationFailed, \(descriptionOfLastError())") } var addr = sockaddr_in() addr.sin_len = __uint8_t(sizeof(sockaddr_in)) addr.sin_family = sa_family_t(AF_INET) addr.sin_port = Int(OSHostByteOrder()) == OSLittleEndian ? _OSSwapInt16(port) : port addr.sin_addr = in_addr(s_addr: inet_addr("0.0.0.0")) addr.sin_zero = (0, 0, 0, 0, 0, 0, 0, 0) var bind_addr = sockaddr() memcpy(&bind_addr, &addr, Int(sizeof(sockaddr_in))) if bind(socketFileDescriptor, &bind_addr, socklen_t(sizeof(sockaddr_in))) == -1 { let details = descriptionOfLastError() release(socketFileDescriptor) return (false, "\(port), BindFailed, \(details)") } if listen(socketFileDescriptor, SOMAXCONN ) == -1 { let details = descriptionOfLastError() release(socketFileDescriptor) return (false, "\(port), ListenFailed, \(details)") } release(socketFileDescriptor) return (true, "\(port) is free for use") } func release(socket: Int32) { Darwin.shutdown(socket, SHUT_RDWR) close(socket) } func descriptionOfLastError() -> String { return String.fromCString(UnsafePointer(strerror(errno))) ?? "Error: \(errno)" }
q5lcpyga2#
更新Swift 4的正确答案:
func checkTcpPortForListen(port: in_port_t) -> (Bool, descr: String) { let socketFileDescriptor = socket(AF_INET, SOCK_STREAM, 0) if socketFileDescriptor == -1 { return (false, "SocketCreationFailed, \(descriptionOfLastError())") } var addr = sockaddr_in() let sizeOfSockkAddr = MemoryLayout<sockaddr_in>.size addr.sin_len = __uint8_t(sizeOfSockkAddr) addr.sin_family = sa_family_t(AF_INET) addr.sin_port = Int(OSHostByteOrder()) == OSLittleEndian ? _OSSwapInt16(port) : port addr.sin_addr = in_addr(s_addr: inet_addr("0.0.0.0")) addr.sin_zero = (0, 0, 0, 0, 0, 0, 0, 0) var bind_addr = sockaddr() memcpy(&bind_addr, &addr, Int(sizeOfSockkAddr)) if Darwin.bind(socketFileDescriptor, &bind_addr, socklen_t(sizeOfSockkAddr)) == -1 { let details = descriptionOfLastError() release(socket: socketFileDescriptor) return (false, "\(port), BindFailed, \(details)") } if listen(socketFileDescriptor, SOMAXCONN ) == -1 { let details = descriptionOfLastError() release(socket: socketFileDescriptor) return (false, "\(port), ListenFailed, \(details)") } release(socket: socketFileDescriptor) return (true, "\(port) is free for use") } func release(socket: Int32) { Darwin.shutdown(socket, SHUT_RDWR) close(socket) } func descriptionOfLastError() -> String { return String.init(cString: (UnsafePointer(strerror(errno)))) }
EDIT:调用此函数的示例:
var portNum: UInt16 = 0 for i in 50000..<65000 { let (isFree, _) = checkTcpPortForListen(port: UInt16(i)) if isFree == true { portNum = UInt16(i) break; } }
2条答案
按热度按时间lpwwtiir1#
主要代码取自Swifter:https://github.com/glock45/swifter
q5lcpyga2#
更新Swift 4的正确答案:
EDIT:调用此函数的示例: