我似乎无法接受TCP连接Grand Central Dispatch来源(dispatch_source_t
),我无法理解我可能做错了什么。我经历了很多材料,但我仍然无法接近(Apple's own documentation,Mike Ash's blog等。)
当然,我可以简单地使用第三方库(GitHub上有很多)但我正试图从中学习。谢谢。
我知道服务器在端口上正在侦听,因为使用telnet 127.0.0.1 6666
超时(但从未实际连接),而任何其他端口立即失败。我希望accept()
连接的代码段永远不会运行。
class MyServer {
func startServing(#port: UInt16 = 6666) {
// Create a listeningSocket on TCP/IPv4.
println("\nStarting TCP server.\nCreating a listening Socket.")
let listeningSocket = socket(AF_INET, SOCK_STREAM, 0 /*IPPROTO_TCP*/)
if listeningSocket == -1 {
println("Failed!")
return
}
// Prepare an socket address.
var no_sig_pipe: Int32 = 1
setsockopt(listeningSocket, SOL_SOCKET, SO_NOSIGPIPE, &no_sig_pipe, socklen_t(sizeof(Int32)))
// Working around Swift's strict initialization policies
var addr = sockaddr_in( sin_len: __uint8_t(sizeof(sockaddr_in))
, sin_family: sa_family_t(AF_INET)
, sin_port: CFSwapInt16HostToBig(port)
, sin_addr: in_addr(s_addr: inet_addr("0.0.0.0"))
, sin_zero: (0, 0, 0, 0, 0, 0, 0, 0) )
var sock_addr = sockaddr( sa_len: 0
, sa_family: 0
, sa_data: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) )
memcpy(&sock_addr, &addr, UInt(sizeof(sockaddr_in)))
// bind() the socket to the address.
println("Binding socket to \(port).")
if bind(listeningSocket, &sock_addr, socklen_t(sizeof(sockaddr_in))) == POSIXSocketError {
println("Failed!")
close(listeningSocket)
return
}
// If we still have a working socket at this point...
if listeningSocket >= 0 {
println("Creating GCD Source.")
connectionSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, UInt(listeningSocket), 0, dispatch_get_global_queue(0,0) /*serverQueue*/)
if connectionSource == .None {
println("Failed!")
close(listeningSocket)
return
}
let myself = self
dispatch_source_set_event_handler( connectionSource, {
// *** This NEVER gets called!! ***
dispatch_async(dispatch_get_main_queue(), { println("GCD Src fired.") })
println("GCD Source triggered.")
myself.acceptConnections(listeningSocket)
})
dispatch_resume(connectionSource)
}
} // end func
} // end class
答案 0 :(得分:0)
在您致电listen
后,您似乎忘记了bind
。来自Mike Ash's blog:
在套接字绑定的情况下,下一步是告诉系统监听 在上面。你猜对了,这是听功能。它 有两个参数:要操作的套接字和所需的长度 用于收听的队列此队列长度告诉系统 在尝试时,您希望它连接多少个传入连接 将这些连接交给您的程序。除非你有好处 使用其他东西的理由,通过SOMAXCONN给你一个安全的, 价值很高。
因此,在您bind
调用和错误检查之后,在创建调度源之前,请添加以下内容:
if listen(listeningSocket, SOMAXCONN) != 0 {
println("Listen Failed!")
close(listeningSocket)
return
}
我将快速测试与您的代码以及上述更改拼凑在一起,当发生与套接字的连接时,这会触发大量GCD Src fired.
和GCD Source triggered.
消息。