gpt4 book ai didi

c - DispatchReadSource 事件处理程序未针对绑定(bind)套接字触发

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

我正在尝试在 Swift 中实现一个简单的 TCP 套接字服务器。此代码应该与 C 实现非常相似,但具有额外的 Swift 主义。

我正在尝试使用curl http://localhost:8080进行连接,即使服务器中没有HTTP逻辑,它至少应该触发“接受”。 curl 的响应是连接被拒绝

这是我正在使用的代码。它输出 2 行“正在监听描述符”,但没有“正在接受...”行

import LibC
import Dispatch

let port = 8080
let listenBacklogLen = 16

// Setup Sockets
let socketDescriptor = (
ipv4: socket(PF_INET, SOCK_STREAM, IPPROTO_TCP),
ipv6: socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP)
)
let descriptors = [socketDescriptor.ipv4, socketDescriptor.ipv6]

var address = (
ipv4: sockaddr_in(),
ipv6: sockaddr_in6()
)

address.ipv4.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
address.ipv4.sin_family = sa_family_t(AF_INET)
address.ipv4.sin_port = in_port_t(port)
address.ipv4.sin_addr.s_addr = INADDR_ANY

address.ipv6.sin6_len = UInt8(MemoryLayout<sockaddr_in>.size)
address.ipv6.sin6_family = sa_family_t(AF_INET6)
address.ipv6.sin6_port = in_port_t(port)
address.ipv6.sin6_addr = in6addr_any

var reuseAddress: Int = 1
let reuseAddressLen = socklen_t(MemoryLayout.size(ofValue: reuseAddress))
withUnsafePointer(to: &reuseAddress) { ref in
for descriptor in descriptors {
assert(setsockopt(descriptor, SOL_SOCKET, SO_REUSEADDR, ref, reuseAddressLen) == 0)
}
}

withUnsafePointer(to: &address.ipv4) { ref in
ref.withMemoryRebound(to: sockaddr.self, capacity: 1) { reboundRef in
assert(bind(socketDescriptor.ipv4, reboundRef, socklen_t(MemoryLayout.size(ofValue: ref.pointee))) == 0)
}
}
withUnsafePointer(to: &address.ipv6) { ref in
ref.withMemoryRebound(to: sockaddr.self, capacity: 1) { reboundRef in
assert(bind(socketDescriptor.ipv6, reboundRef, socklen_t(MemoryLayout.size(ofValue: ref.pointee))) == 0)
}
}

var acceptSources: [DispatchSourceRead] = []
var requestSources: [DispatchSourceRead] = []
for descriptor in descriptors {
assert(listen(descriptor, Int32(listenBacklogLen)) == 0);

let source = DispatchSource.makeReadSource(fileDescriptor: descriptor, queue: .global(qos: .userInitiated))
source.setEventHandler {
print("Accepting…")
var address = sockaddr()
var addressLen: socklen_t = socklen_t(MemoryLayout.size(ofValue: address))
let requestSocketDescriptor = accept(descriptor, &address, &addressLen)
assert(requestSocketDescriptor >= 0)

let source = DispatchSource.makeReadSource(fileDescriptor: requestSocketDescriptor, queue: .global(qos: .userInitiated))
source.setEventHandler { [unowned source] in
var char: CChar = 0
let bytesRead = read(requestSocketDescriptor, &char, 1)
switch bytesRead {
case -1:
if ![EAGAIN, EINTR].contains(errno) {
print("Read returned error (\(errno)): \(strerror(errno))")
fallthrough
}
case 0:
print("Done")
source.cancel()
default:
print("C: \(char)")
}
}
requestSources.append(source)
source.resume()
}
acceptSources.append(source)

print("Listening on descriptor: \(descriptor)")
source.resume()
}

dispatchMain()

顺便说一句,LibC 是一个简单的模块,它统一了 glibc 和 Darwin:

#if os(Linux)
@_exported import Glibc
#else
@_exported import Darwin.C
#endif

最佳答案

啊哈!端口必须是大尾数:address.ipv4.sin_port = in_port_t(port).bigEndianaddress.ipv6.sin_port = in_port_t(port).bigEndian

Socket Server Example with Swift 的帮助下解决了这个问题

关于c - DispatchReadSource 事件处理程序未针对绑定(bind)套接字触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45622642/

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