2017-08-10 1 views
0

J'essaie d'implémenter un serveur de socket TCP simple dans Swift. Ce code devrait être assez similaire à une implémentation C mais avec des Swift-isms supplémentaires.Le gestionnaire d'événements DispatchReadSource ne se déclenche pas pour le socket lié

J'essaye de me connecter en utilisant curl http://localhost:8080 qui devrait au moins déclencher un "accepter" même s'il n'y a pas de logique HTTP dans le serveur. La réponse de curl est Connection refused

Voici le code que j'utilise. Il émet 2 "Écoute le descripteur" lignes, mais pas "Acceptant ..." lignes

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() 

BTW, libc est un module simple qui unifie glibc et Darwin:

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

Répondre