Socket Framework pour Swift à l'aide du gestionnaire de packages Swift. Fonctionne sur iOS, macOS et Linux.
swift-5.1-RELEASE Toolkain ( minimum requis pour la dernière version )swift-5.4-RELEASE Toolkain ( recommandé )Note:
Si vous créez un serveur UDP sur iOS, vous devrez peut-être suivre quelques étapes:
Pour construire une prise à partir de la ligne de commande:
% cd <path-to-clone>
% swift build
Pour exécuter les tests unitaires fournis pour Socket à partir de la ligne de commande:
% cd <path-to-clone>
% swift build
% swift test
Pour inclure Bluesocket dans un package Swift Package Manager, ajoutez-le à l'attribut dependencies défini dans votre fichier Package.swift . Vous pouvez sélectionner la version en utilisant les paramètres majorVersion et minor . Par exemple:
dependencies: [
.Package(url: "https://github.com/Kitura/BlueSocket.git", majorVersion: <majorVersion>, minor: <minor>)
]
Pour inclure Bluesocket dans un projet à l'aide de Carthage, ajoutez une ligne à votre Cartfile avec l'organisation GitHub et les noms et la version de projet. Par exemple:
github "Kitura/BlueSocket" ~> <majorVersion>.<minor>
Pour inclure Bluesocket dans un projet à l'aide de Cocoapods, vous ajoutez simplement BlueSocket à votre Podfile , par exemple:
platform :ios, '10.0'
target 'MyApp' do
use_frameworks!
pod 'BlueSocket'
end
La première chose que vous devez faire est d'importer le cadre de socket. Cela se fait par ce qui suit:
import Socket
Bluesocket soutient les familles, types et protocoles suivants:
Socket.ProtocolFamily.inetSocket.ProtocolFamily.inet6Socket.ProtocolFamily.unixSocket.SocketType.streamSocket.SocketType.datagramSocket.SocketProtocol.tcpSocket.SocketProtocol.udpSocket.SocketProtocol.unixBluesocket fournit quatre méthodes d'usine différentes qui sont utilisées pour créer une instance. Ce sont:
create() - Cela crée une prise par défaut entièrement configurée. Une prise par défaut est créée avec family: .inet , type: .stream et proto: .tcp .create(family family: ProtocolFamily, type: SocketType, proto: SocketProtocol) - Cette API vous permet de créer une instance Socket configurée personnalisée pour vos besoins. Vous pouvez personnaliser la famille du protocole, le type de socket et le protocole de socket.create(connectedUsing signature: Signature) - Cette API vous permettra de créer une instance Socket et de lui faire tenter de se connecter à un serveur en fonction des informations que vous transmettez dans le Socket.Signature .create(fromNativeHandle nativeHandle: Int32, address: Address?) - Cette API vous permet d'envelopper un descripteur de fichiers natif décrivant une prise existante dans une nouvelle instance de Socket . Bluesocket vous permet de définir la taille du tampon de lecture qu'il utilisera. Ensuite, selon les besoins de l'application, vous pouvez le changer en valeur supérieure ou inférieure. La valeur par défaut est définie sur Socket.SOCKET_DEFAULT_READ_BUFFER_SIZE qui a une valeur de 4096 . La taille minimale du tampon de lecture est Socket.SOCKET_MINIMUM_READ_BUFFER_SIZE qui est définie sur 1024 . Ci-dessous, illustre comment modifier la taille du tampon de lecture (manipulation des exceptions omise pour la concision):
let mySocket = try Socket.create()
mySocket.readBufferSize = 32768
L'exemple ci-dessus définit la taille du tampon de lecture par défaut sur 32768 . Ce paramètre doit être effectué avant d'utiliser l'instance Socket pour la première fois.
Pour fermer la prise d'une instance ouverte, la fonction suivante est fournie:
close() - Cette fonction effectuera les tâches nécessaires afin de fermer proprement une prise ouverte.Pour utiliser Bluesocket pour écouter une connexion sur une prise, l'API suivante est fournie:
listen(on port: Int, maxBacklogSize: Int = Socket.SOCKET_DEFAULT_MAX_BACKLOG, allowPortReuse: Bool = true, node: String? = nil) Le premier port de paramètre, le port est-il utilisé pour écouter. Le deuxième paramètre, maxBacklogSize vous permet de définir la taille des connexions en attente de la file d'attente. La fonction déterminera la configuration de socket appropriée en fonction du port spécifié. Pour plus de commodité sur macOS, le Socket.SOCKET_MAX_DARWIN_BACKLOG constant.socket_max_darwin_backlog peut être défini pour utiliser la taille maximale du backlog autorisé. La valeur par défaut pour toutes les plates-formes est Socket.SOCKET_DEFAULT_MAX_BACKLOG , actuellement définie sur 50 . Pour l'utilisation du serveur, il peut être nécessaire d'augmenter cette valeur. Pour permettre la réutilisation du port d'écoute, définissez allowPortReuse à true . S'il est défini sur false , une erreur se produira si vous essayez d'écouter sur un port déjà utilisé. Le comportement DEFAULT consiste à allow la réutilisation du port. Le dernier paramètre, node , peut être utilisé pour écouter sur une adresse spécifique . La valeur réalisée est une chaîne facultative contenant l'adresse réseau numérique (pour IPv4, notation et notation des points, pour IPv6, String hexidécimal). Le comportement DEFAULT consiste à rechercher une interface appropriée. Si node est mal formaté, une erreur socket_err_getaddrinfo_failed sera renvoyée. Si node est correctement formaté mais que l'adresse spécifiée n'est pas disponible, un socket_err_bind_failed sera retourné.listen(on path: String, maxBacklogSize: Int = Socket.SOCKET_DEFAULT_MAX_BACKLOG) Cette API ne peut être utilisée qu'avec la famille du protocole .unix . Le premier path de paramètre, est le chemin à utiliser pour écouter. Le deuxième paramètre, maxBacklogSize vous permet de définir la taille des connexions en attente de la file d'attente. La fonction déterminera la configuration de socket appropriée en fonction du port spécifié. Pour plus de commodité sur macOS, le Socket.SOCKET_MAX_DARWIN_BACKLOG constant.socket_max_darwin_backlog peut être défini pour utiliser la taille maximale du backlog autorisé. La valeur par défaut pour toutes les plates-formes est Socket.SOCKET_DEFAULT_MAX_BACKLOG , actuellement définie sur 50 . Pour l'utilisation du serveur, il peut être nécessaire d'augmenter cette valeur. L'exemple suivant crée une instance Socket par défaut, puis commence immédiatement à écouter sur le port 1337 . Remarque: Gestion des exceptions omise pour la concision, voir l'exemple complet ci-dessous pour un exemple de gestion des exceptions.
var socket = try Socket . create ( )
try socket . listen ( on : 1337 )Lorsqu'un socket d'écoute détecte une demande de connexion entrante, le contrôle est renvoyé à votre programme. Vous pouvez ensuite accepter la connexion ou continuer à écouter ou les deux si votre application est multithread. Bluesocket prend en charge deux façons distinctes d'accepter une connexion entrante. Ils sont:
acceptClientConnection(invokeDelegate: Bool = true) - Cette fonction accepte la connexion et renvoie une nouvelle instance Socket basée sur le socket nouvellement connecté. L'instance qui écoutait sans être affectée. Si invokeDelegate est false et que le Socket a un délégué SSLService connecté, vous devez appeler la méthode invokeDelegateOnAccept à l'aide de l'instance Socket qui est renvoyée par cette fonction.invokeDelegateOnAccept(for newSocket: Socket) - Si l'instance Socket a un délégué SSLService , cela invoquera la fonction d'accepter les délégués pour effectuer une négociation SSL. Il doit être appelé avec l'instance Socket renvoyée par acceptClientConnection . Cette fonction lancera une exception si elle est appelée avec la mauvaise instance Socket , appelée plusieurs fois, ou si l'instance Socket n'a pas de délégué SSLService .acceptConnection() - Cette fonction accepte la connexion entrante, en remplaçant et en fermant la prise d'écoute existante. Les propriétés autrefois associées à la prise d'écoute sont remplacées par les propriétés pertinentes pour la prise nouvellement connectée. En plus de la create(connectedUsing:) Méthode d'usine décrite ci-dessus, Bluesocket prend en charge trois fonctions d'instance supplémentaires pour connecter une instance Socket à un serveur. Ils sont:
connect(to host: String, port: Int32, timeout: UInt = 0) - Cette API vous permet de vous connecter à un serveur en fonction du hostname et port que vous fournissez. Remarque: Une exception sera lancée par cette fonction si la valeur du port n'est pas dans la plage 1-65535 . Facultativement, vous pouvez définir timeout sur le nombre de millisecondes pour attendre la connexion. Remarque: Si la prise est en mode de blocage, elle sera temporairement changée en mode non bloquant si un timeout supérieur à zéro (0) est fourni. La prise retournée sera remise à son paramètre d'origine (blocage ou non bloquant) . Si le socket est défini sur le non-blocage et qu'aucune valeur de délai d'expiration n'est fournie , une exception sera lancée. Alternativement, vous pouvez régler la prise sur le non-blocage après la connexion avec succès.connect(to path: String) - Cette API ne peut être utilisée qu'avec la famille du protocole .unix . Il vous permet de vous connecter à un serveur en fonction du path que vous fournissez.connect(using signature: Signature) - Cette API vous permet de spécifier les informations de connexion en fournissant une instance Socket.Signature contenant les informations. Reportez-vous à Socket.Signature dans Socket.Swift pour plus d'informations.Bluesocket prend en charge quatre façons différentes de lire les données d'une prise. Ce sont (dans l'ordre d'utilisation recommandé):
read(into data: inout Data) - Cette fonction lit toutes les données disponibles sur une prise et les renvoie dans l'objet Data qui a été passé.read(into data: NSMutableData) - Cette fonction lit toutes les données disponibles sur une prise et les renvoie dans l'objet NSMutableData qui a été passé.readString() - Cette fonction lit toutes les données disponibles sur une prise et les renvoie sous forme de String . Un nil est retourné si aucune donnée n'est disponible pour la lecture.read(into buffer: UnsafeMutablePointer<CChar>, bufSize: Int, truncate: Bool = false) - Cette fonction vous permet de lire les données dans un tampon d'une taille spécifiée en fournissant un pointeur dangereux vers ce tampon et un entier de la taille de ce tampon. Cette API (en plus d'autres types d'exceptions) lancera un Socket.SOCKET_ERR_RECV_BUFFER_TOO_SMALL si le tampon fourni est trop petit, sauf si truncate = true dans ce cas, le socket agira comme si seuls les octets bufSize étaient lus (les décotes non remise en cause seront retournées dans le prochain appel). Si truncate = false , vous devrez rappeler à nouveau avec une taille de tampon appropriée (voir Error.bufferSizeNeeded dans socket.swift pour plus d'informations).readString() peuvent renvoyer zéro (0). Cela peut indiquer que la connexion distante a été fermée ou cela pourrait indiquer que la prise se bloquerait (en supposant que vous avez désactivé le blocage). Pour différencier les deux, la propriété remoteConnectionClosed peut être vérifiée. Si true , le partenaire distant de socket a fermé la connexion et cette instance Socket doit être fermée.En plus de lire à partir d'une prise, Bluesocket fournit également quatre méthodes d'écriture de données dans une prise. Ce sont (dans l'ordre d'utilisation recommandé):
write(from data: Data) - Cette fonction écrit les données contenues dans l'objet Data à la prise.write(from data: NSData) - Cette fonction écrit les données contenues dans l'objet NSData à la prise.write(from string: String) - Cette fonction écrit les données contenues dans la String fournie à la prise.write(from buffer: UnsafeRawPointer, bufSize: Int) - Cette fonction écrit les données contenues dans le tampon de la taille spécifiée en fournissant un pointeur dangereux vers ce tampon et un entier qui dénote la taille de ce tampon.Bluesocket prend en charge trois façons différentes d'écouter les datagrammes entrants. Ce sont (dans l'ordre d'utilisation recommandé):
listen(forMessage data: inout Data, on port: Int, maxBacklogSize: Int = Socket.SOCKET_DEFAULT_MAX_BACKLOG) - Cette fonction écoute un datagramme entrant, les lit et les renvoie dans l'objet Data passées. Il renvoie un tuple contenant le nombre d'octets lus et l' Address de l'origine des données.listen(forMessage data: NSMutableData, on port: Int, maxBacklogSize: Int = Socket.SOCKET_DEFAULT_MAX_BACKLOG) - Cette fonction écoute un datagramme entrant, le lit et le renvoie dans l'objet NSMutableData passé. Il renvoie un tuple contenant le nombre d'octets lus et l' Address de l'origine des données.listen(forMessage buffer: UnsafeMutablePointer<CChar>, bufSize: Int, on port: Int, maxBacklogSize: Int = Socket.SOCKET_DEFAULT_MAX_BACKLOG) - cette fonction écoute un datagramme entrant, les lit et les renvoie dans l'objet Data passé. Il renvoie un tuple contenant le nombre d'octets lus et l' Address de l'origine des données.port spécifié. La définition de la valeur du port sur zéro (0) entraînera la fonction de déterminer un port libre approprié.maxBacklogSize vous permet de définir la taille de la file d'attente en attendant les connexions en attente. La fonction déterminera la configuration de socket appropriée en fonction du port spécifié. Pour plus de commodité sur macOS, le Socket.SOCKET_MAX_DARWIN_BACKLOG constant.socket_max_darwin_backlog peut être défini pour utiliser la taille maximale du backlog autorisé. La valeur par défaut pour toutes les plates-formes est Socket.SOCKET_DEFAULT_MAX_BACKLOG , actuellement définie sur 50 . Pour l'utilisation du serveur, il peut être nécessaire d'augmenter cette valeur.Bluesocket prend en charge trois façons différentes de lire les datagrammes entrants. Ce sont (dans l'ordre d'utilisation recommandé):
readDatagram(into data: inout Data) - Cette fonction lit un datagramme entrant et les renvoie dans l'objet Data passés. Il renvoie un tuple contenant le nombre d'octets lus et l' Address de l'origine des données.readDatagram(into data: NSMutableData) - Cette fonction lit un datagramme entrant et le renvoie dans l'objet NSMutableData passé. Il renvoie un tuple contenant le nombre d'octets lus et l' Address de l'origine des données.readDatagram(into buffer: UnsafeMutablePointer<CChar>, bufSize: Int) - Cette fonction lit un datagramme entrant et les renvoie dans l'objet Data passés. Il renvoie un tuple contenant le nombre d'octets lus et l' Address de l'origine des données. Si la quantité de données de lecture est plus que bufSize seuls bufSize sera retourné. Le reste de la lecture des données sera rejeté.Bluesocket fournit également quatre méthodes pour écrire des datagrammes sur une prise. Ce sont (dans l'ordre d'utilisation recommandé):
write(from data: Data, to address: Address) - Cette fonction écrit le datagramme contenu dans l'objet Data à la prise.write(from data: NSData, to address: Address) - Cette fonction écrit le datagramme contenu dans l'objet NSData à la prise.write(from string: String, to address: Address) - Cette fonction écrit le datagramme contenu dans la String fournie à la prise.write(from buffer: UnsafeRawPointer, bufSize: Int, to address: Address) - Cette fonction écrit les données contenues dans le tampon de la taille spécifiée en fournissant un pointeur dangereux sur ce tampon et un entier qui dénote la taille de ce tampon.address représente l'adresse de la destination à laquelle vous envoyez le datagramme. Les API de lecture et d'écriture ci-dessus qui utilisent NSData ou NSMutableData seront probablement obsolètes dans un avenir pas si lointain.
hostnameAndPort(from address: Address) - Cette fonction de classe fournit un moyen d'extraire le nom d'hôte et le port à partir d'un Socket.Address donné.Address. À la réussite, un tuple contenant le hostname et port sont retournés.checkStatus(for sockets: [Socket]) - Cette fonction de classe vous permet de vérifier l'état d'un tableau d'instances Socket . Une fois terminé, un tuple contenant deux tableaux Socket est renvoyé. Le premier tableau contient les instances Socket qui ont des données disponibles à lire et le deuxième tableau contient des instances Socket auxquelles peut être écrit. Cette API ne bloque pas . Il vérifiera l'état de chaque instance Socket , puis renverra les résultats.wait(for sockets: [Socket], timeout: UInt, waitForever: Bool = false) - Cette fonction de classe permet de surveiller un tableau d'instances Socket , en attendant qu'un délai d'expiration se produise ou des données sont lisibles dans l'une des instances Socket surveillées. Si un délai d'expiration de zéro (0) est spécifié, cette API vérifiera chaque prise et reviendra immédiatement. Sinon, il attendra que le délai d'expiration expire ou que les données soient lisibles à partir d'une ou plusieurs des instances Socket surveillées. Si un délai d'expiration se produit, cette API retournera nil . Si des données sont disponibles sur une ou plusieurs des instances Socket surveillées, ces instances seront renvoyées dans un tableau. Si l'indicateur waitForever est défini sur true, la fonction attendra indéfiniment que les données deviennent disponibles quelle que soit la valeur de délai d'expiration spécifiée .createAddress(host: String, port: Int32) - Cette fonction de classe permet la création de l'énumération Address compte tenu d'un host et port . Au cours de la réussite, cette fonction renvoie une Address ou nil si l' host spécifié n'existe pas.isReadableOrWritable(waitForever: Bool = false, timeout: UInt = 0) - Cette fonction d'instance permet de déterminer si une instance Socket est lisible et / ou écrivable. Un tuple est renvoyé contenant deux valeurs Bool . Le premier, s'il est vrai, indique que l'instance Socket a des données à lire, la seconde, si elle est vraie, indique que l'instance Socket peut être écrite. waitForever si vrai, fait attendre cette routine que la Socket est lisible ou écrivative ou une erreur se produit. Si faux, le paramètre timeout spécifie combien de temps attendre. Si une valeur de zéro (0) est spécifiée pour la valeur de délai d'expiration, cette fonction vérifiera l'état actuel et renvoie immédiatement . Cette fonction renvoie un tuple contenant deux booléens, le premier readable et le second, writable . Ils sont définis sur TRUE si la Socket est lisible ou écrivative. Si aucun n'est défini sur True, un délai d'expiration s'est produit. Remarque: Si vous essayez d'écrire dans une prise nouvellement connectée, vous devez vous assurer qu'elle est écrite avant d'essayer l'opération.setBlocking(shouldBlock: Bool) - Cette fonction d'instance vous permet de contrôler si cette instance Socket doit être placée ou non en mode de blocage ou non. Remarque: toutes les instances Socket sont, par défaut , créées en mode de blocage .setReadTimeout(value: UInt = 0) - Cette fonction d'instance vous permet de définir un délai d'expiration pour les opérations de lecture. value est un UInt , le temps d'attente de l'opération de lecture avant de revenir. En cas de délai d'attente, l'opération de lecture retournera 0 octets Read et errno sera défini sur EAGAIN .setWriteTimeout(value: UInt = 0) - Cette fonction d'instance vous permet de définir un délai d'expiration pour les opérations d'écriture. value est un UInt , le temps d'attente de l'opération d'écriture avant de retourner. En cas de délai d'attente, l'opération d'écriture renverra 0 octets écrits et errno sera défini sur EAGAIN pour TCP et UNIX Sockets, pour UDP , l'opération d'écriture réussira quelle que soit la valeur de temps mort.udpBroadcast(enable: Bool) - Cette fonction d'instance est utilisée pour activer le mode de diffusion sur une prise UDP. Passer true à l'activation de diffusion, false à désactiver. Cette fonction lancera une exception si l'instance Socket n'est pas une prise UDP. L'exemple suivant montre comment créer un serveur d'écho multi-thread relativement simple à l'aide de la nouvelle API de répartition GCD based . Ce qui suit est le code pour un simple serveur d'écho qui, une fois en cours d'exécution, peut être accessible via telnet ::1 1337 .
import Foundation
import Socket
import Dispatch
class EchoServer {
static let quitCommand : String = " QUIT "
static let shutdownCommand : String = " SHUTDOWN "
static let bufferSize = 4096
let port : Int
var listenSocket : Socket ? = nil
var continueRunningValue = true
var connectedSockets = [ Int32 : Socket ] ( )
let socketLockQueue = DispatchQueue ( label : " com.kitura.serverSwift.socketLockQueue " )
var continueRunning : Bool {
set ( newValue ) {
socketLockQueue . sync {
self . continueRunningValue = newValue
}
}
get {
return socketLockQueue . sync {
self . continueRunningValue
}
}
}
init ( port : Int ) {
self . port = port
}
deinit {
// Close all open sockets...
for socket in connectedSockets . values {
socket . close ( )
}
self . listenSocket ? . close ( )
}
func run ( ) {
let queue = DispatchQueue . global ( qos : . userInteractive )
queue . async { [ unowned self ] in
do {
// Create an IPV6 socket...
try self . listenSocket = Socket . create ( family : . inet6 )
guard let socket = self . listenSocket else {
print ( " Unable to unwrap socket... " )
return
}
try socket . listen ( on : self . port )
print ( " Listening on port: ( socket . listeningPort ) " )
repeat {
let newSocket = try socket . acceptClientConnection ( )
print ( " Accepted connection from: ( newSocket . remoteHostname ) on port ( newSocket . remotePort ) " )
print ( " Socket Signature: ( String ( describing : newSocket . signature ? . description ) ) " )
self . addNewConnection ( socket : newSocket )
} while self . continueRunning
}
catch let error {
guard let socketError = error as? Socket . Error else {
print ( " Unexpected error... " )
return
}
if self . continueRunning {
print ( " Error reported: n ( socketError . description ) " )
}
}
}
dispatchMain ( )
}
func addNewConnection ( socket : Socket ) {
// Add the new socket to the list of connected sockets...
socketLockQueue . sync { [ unowned self , socket ] in
self . connectedSockets [ socket . socketfd ] = socket
}
// Get the global concurrent queue...
let queue = DispatchQueue . global ( qos : . default )
// Create the run loop work item and dispatch to the default priority global queue...
queue . async { [ unowned self , socket ] in
var shouldKeepRunning = true
var readData = Data ( capacity : EchoServer . bufferSize )
do {
// Write the welcome string...
try socket . write ( from : " Hello, type 'QUIT' to end session n or 'SHUTDOWN' to stop server. n " )
repeat {
let bytesRead = try socket . read ( into : & readData )
if bytesRead > 0 {
guard let response = String ( data : readData , encoding : . utf8 ) else {
print ( " Error decoding response... " )
readData . count = 0
break
}
if response . hasPrefix ( EchoServer . shutdownCommand ) {
print ( " Shutdown requested by connection at ( socket . remoteHostname ) : ( socket . remotePort ) " )
// Shut things down...
self . shutdownServer ( )
return
}
print ( " Server received from connection at ( socket . remoteHostname ) : ( socket . remotePort ) : ( response ) " )
let reply = " Server response: n ( response ) n "
try socket . write ( from : reply )
if ( response . uppercased ( ) . hasPrefix ( EchoServer . quitCommand ) || response . uppercased ( ) . hasPrefix ( EchoServer . shutdownCommand ) ) &&
( !response . hasPrefix ( EchoServer . quitCommand ) && !response . hasPrefix ( EchoServer . shutdownCommand ) ) {
try socket . write ( from : " If you want to QUIT or SHUTDOWN, please type the name in all caps. ? n " )
}
if response . hasPrefix ( EchoServer . quitCommand ) || response . hasSuffix ( EchoServer . quitCommand ) {
shouldKeepRunning = false
}
}
if bytesRead == 0 {
shouldKeepRunning = false
break
}
readData . count = 0
} while shouldKeepRunning
print ( " Socket: ( socket . remoteHostname ) : ( socket . remotePort ) closed... " )
socket . close ( )
self . socketLockQueue . sync { [ unowned self , socket ] in
self . connectedSockets [ socket . socketfd ] = nil
}
}
catch let error {
guard let socketError = error as? Socket . Error else {
print ( " Unexpected error by connection at ( socket . remoteHostname ) : ( socket . remotePort ) ... " )
return
}
if self . continueRunning {
print ( " Error reported by connection at ( socket . remoteHostname ) : ( socket . remotePort ) : n ( socketError . description ) " )
}
}
}
}
func shutdownServer ( ) {
print ( " n Shutdown in progress... " )
self . continueRunning = false
// Close all open sockets...
for socket in connectedSockets . values {
self . socketLockQueue . sync { [ unowned self , socket ] in
self . connectedSockets [ socket . socketfd ] = nil
socket . close ( )
}
}
DispatchQueue . main . sync {
exit ( 0 )
}
}
}
let port = 1337
let server = EchoServer ( port : port )
print ( " Swift Echo Server Sample " )
print ( " Connect with a command line window by entering 'telnet ::1 ( port ) ' " )
server . run ( ) Ce serveur peut être construit en spécifiant le fichier Package.swift suivant à l'aide de Swift 4.
import PackageDescription
let package = Package (
name : " EchoServer " ,
dependencies : [
. package ( url : " https://github.com/Kitura/BlueSocket.git " , from : " 1.0.8 " ) ,
] ,
targets : [
. target (
name : " EchoServer " ,
dependencies : [
" Socket "
] ) ,
]
) Ou si vous utilisez toujours Swift 3, en spécifiant le fichier Package.swift suivant.
import PackageDescription
let package = Package (
name : " EchoServer " ,
dependencies : [
. Package ( url : " https://github.com/Kitura/BlueSocket.git " , majorVersion : 1 , minor : 0 ) ,
] ,
exclude : [ " EchoServer.xcodeproj " ]
) La séquence de commandes suivante créera et exécutera le serveur Echo sur Linux. Si vous exécutez sur macOS ou avec n'importe quelle chaîne d'outils plus récente que la chaîne d'outils 8/18, vous pouvez omettre le commutateur -Xcc -fblocks car il n'est plus nécessaire.
$ swift build -Xcc -fblocks
$ .build/debug/EchoServer
Swift Echo Server Sample
Connect with a command line window by entering 'telnet ::1 1337'
Listening on port: 1337
Nous aimons parler côté serveur Swift et Kitura. Rejoignez notre Slack pour rencontrer l'équipe!
Cette bibliothèque est sous licence sous Apache 2.0. Le texte complet de licence est disponible en licence.