# Serveur TCP dans une application iOS utilisant les sockets POSIX : De la théorie à la pratique
Dans le développement iOS, la pile réseau couvre tout, des requêtes HTTP de haut niveau aux sockets BSD de bas niveau. URLSession est idéal pour les opérations HTTP et WebSocket standard, le framework Network gère TCP/UDP avec TLS, et CFNetwork prend en charge les anciens protocoles comme FTP et Bonjour. L’API POSIX fournit un accès direct à la couche transport, tandis que SwiftNIO ajoute des capacités côté serveur en Swift.
Tous ces outils reposent sur des sockets. Pour des protocoles personnalisés (comme SMTP ou IMAP) ou une logique serveur, vous avez besoin d’un accès à la couche transport. Cet article vous guide pas à pas dans l’implémentation d’un serveur TCP utilisant l’API POSIX — dépendances minimales et contrôle total.
Sockets POSIX : Création et configuration
La classe TCPServer encapsule le socket, le port et le cycle de vie :
final class TCPServer {
let port: UInt16
init(port: UInt16 = 8081) {
self.port = port
}
deinit {
stop()
}
func start() throws { }
func stop() { }
}
Les erreurs sont fortement typées :
enum SocketError: LocalizedError {
case socketCreationFailed(errno: Int32)
case bindFailed(errno: Int32)
case listenFailed(errno: Int32)
case writeFailed(errno: Int32)
case writeTimeout
var errorDescription: String? { /* ... */ }
}
Dans start() :
socket(AF_INET, SOCK_STREAM, 0)crée un socket TCP IPv4. Il retourne un descripteur ou -1 en cas d’erreur (vérifiez errno).
setsockoptavecSO_REUSEADDR=1permet de relier l’adresse sans délais TIME_WAIT.
var reuseAddr: Int32 = 1
setsockopt(currentSocket, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, socklen_t(MemoryLayout<Int32>.size))
Liaison, écoute et gestion des connexions
La structure d’adresse sockaddr_in est remplie pour INADDR_ANY (0.0.0.0) :
var addr = sockaddr_in()
addr.sin_family = sa_family_t(AF_INET)
addr.sin_port = in_port_t(port.bigEndian)
addr.sin_addr.s_addr = in_addr_t(0)
bind(currentSocket, sockaddr_cast(&addr), socklen_t(MemoryLayout<sockaddr_in>.size))
listen(currentSocket, 10) met en file d’attente jusqu’à 10 connexions en attente.
La boucle de gestion s’exécute dans un thread en arrière-plan :
DispatchQueue.global().async { [weak self] in
while let server = self, server.isRunning {
var clientAddr = sockaddr_in()
var len = socklen_t(MemoryLayout<sockaddr_in>.size)
let clientSocket = accept(server.currentSocket, sockaddr_cast(&clientAddr), &len)
// Handle clientSocket
}
}
Analyse HTTP et service de fichiers
Le serveur implémente HTTP/1.1 de base. L’analyseur extrait la méthode, le chemin et les en-têtes de la requête brute.
struct HTTPRequest {
let method: String
let path: String
let headers: [String: String]
let body: Data?
}
Pour GET /files/, il retourne une liste de fichiers du répertoire Documents :
<html><body><h1>App Files</h1><ul>
<li><a href="/file/filename">filename</a></li>
</ul></body></html>
Les téléchargements via /file/ : utilise sendfile pour l’efficacité.
La réponse est construite manuellement :
"HTTP/1.1 200 OK\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: \(data.count)\r\n"
+ "\r\n" + String(data: data, encoding: .utf8)!
Sécurité et limitations
- Réseau local : Le serveur se lie à 0.0.0.0:8081, accessible via l’IP de l’appareil.
- Sandbox : Accès limité à Documents. Pas de fichiers système.
- Timeout : 30 s par requête ; fermer en cas d’erreurs.
- Limitations iOS : Le réseau en arrière-plan nécessite
background-fetchou des entitlements VoIP.
Points clés :
- L’API POSIX est une interface de bas niveau universelle, identique à macOS/Linux.
- SO_REUSEADDR est essentiel pour les redémarrages rapides en développement.
- Exécutez
accept()dans une boucle asynchrone sans bloquer le thread principal. - L’analyse HTTP est minimaliste : méthode + chemin + Content-Length.
sendfile()surpassewrite()pour les gros fichiers.
Tests et débogage
- Lancement :
try server.start() - Accès local :
http://localhost:8081/files - Accès réseau :
http://192.168.1.100:8081/files - Journaux :
print(String(cString: strerror(errno))) - Instruments : Utilisez Network Link Conditioner pour les simulations.
Le projet démontre le cycle complet : du socket à l’interface web. Le code est extensible pour WebSocket ou protocoles personnalisés.
— Editorial Team
Aucun commentaire pour le moment.