-
Usar la simultaneidad estructurada con el marco Network
El marco Network es la mejor forma de realizar conexiones de red de bajo nivel en plataformas de Apple; además, en iOS, iPadOS y macOS 26, se ajusta perfectamente al código de simultaneidad estructurado. Exploraremos cómo puedes realizar conexiones, enviar y recibir datos y mensajes enmarcados, escuchar las conexiones entrantes y explorar la red en busca de servicios. También mencionaremos las prácticas recomendadas clave a lo largo del proceso.
Capítulos
- 0:00 - Te damos la bienvenida
- 0:45 - Hacer conexiones
- 7:22 - Enviar y recibir
- 14:22 - Aceptar conexiones entrantes
- 16:05 - Buscar otros dispositivos
Recursos
Videos relacionados
WWDC25
WWDC18
-
Buscar este video…
-
-
4:04 - Make a connection with TLS
// Make a connection import Network let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { TLS() } -
4:41 - Make a connection with TLS and IP options
// Make a connection import Network let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029) { TLS { TCP { IP() .fragmentationEnabled(false) } } } -
5:07 - Make a connection with customized parameters
// Make a connection import Network let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029), using: .parameters { TLS { TCP { IP() .fragmentationEnabled(false) } } } .constrainedPathsProhibited(true)) -
7:30 - Send and receive on a connection
// Send and receive on a connection import Network public func sendAndReceiveWithTLS() async throws { let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { TLS() } let outgoingData = Data("Hello, world!".utf8) try await connection.send(outgoingData) let incomingData = try await connection.receive(exactly: 98).content print("Received data: \(incomingData)") } -
8:29 - Send and receive on a connection
// Send and receive on a connection import Network public func sendAndReceiveWithTLS() async throws { let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { TLS() } let outgoingData = Data("Hello, world!".utf8) try await connection.send(outgoingData) let remaining32 = try await connection.receive(as: UInt32.self).content guard var remaining = Int(exactly: remaining32) else { /* ... throw an error ... */ } while remaining > 0 { let imageChunk = try await connection.receive(atLeast: 1, atMost: remaining).content remaining -= imageChunk.count // Parse the next portion of the image before continuing } } -
11:06 - Tic-Tac-Toe game messages
// TicTacToe game messages import Network enum GameMessage: Int { case selectedCharacter = 0 case move = 1 } struct GameCharacter: Codable { let character: String } struct GameMove: Codable { let row: Int let column: Int } -
11:24 - Send TicTacToe game messages with TLV
// Send TicTacToe game messages with TLV import Network public func sendWithTLV() async throws { let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { TLV { TLS() } } let characterData = try JSONEncoder().encode(GameCharacter(character: "🐨")) try await connection.send(characterData, type: GameMessage.selectedCharacter.rawValue) } -
11:53 - Receive TicTacToe game messages with TLV
import Network public func receiveWithTLV() async throws { let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { TLV { TLS() } } let (incomingData, metadata) = try await connection.receive() switch GameMessage(rawValue: metadata.type) { case .selectedCharacter: let character = try JSONDecoder().decode(GameCharacter.self, from: incomingData) print("Character selected: \(character)") case .move: let move = try JSONDecoder().decode(GameMove.self, from: incomingData) print("Move: \(move)") case .none: print("Unknown message") } } -
12:50 - Tic-Tac-Toe game messages with Coder
// TicTacToe game messages with Coder import Network enum GameMessage: Codable { case selectedCharacter(String) case move(row: Int, column: Int) } -
13:13 - Send TicTacToe game messages with Coder
// Send TicTacToe game messages with Coder import Network public func sendWithCoder() async throws { let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { Coder(GameMessage.self, using: .json) { TLS() } } let selectedCharacter: GameMessage = .selectedCharacter("🐨") try await connection.send(selectedCharacter) } -
13:53 - Receive TicTacToe game messages with Coder
// Receive TicTacToe game messages with Coder import Network public func receiveWithCoder() async throws { let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { Coder(GameMessage.self, using: .json) { TLS() } } let gameMessage = try await connection.receive().content switch gameMessage { case .selectedCharacter(let character): print("Character selected: \(character)") case .move(let row, let column): print("Move: (\(row), \(column))") } } -
15:16 - Listen for incoming connections with NetworkListener
// Listen for incoming connections with NetworkListener import Network public func listenForIncomingConnections() async throws { try await NetworkListener { Coder(GameMessage.self, using: .json) { TLS() } }.run { connection in for try await (gameMessage, _) in connection.messages { // Handle the GameMessage } } } -
17:39 - Browse for nearby paired Wi-Fi Aware devices
// Browse for nearby paired Wi-Fi Aware devices import Network import WiFiAware public func findNearbyDevice() async throws { let endpoint = try await NetworkBrowser(for: .wifiAware(.connecting(to: .allPairedDevices, from: .ticTacToeService))).run { endpoints in .finish(endpoints.first!) } // Make a connection to the endpoint }
-
-
- 0:00 - Te damos la bienvenida
Obtén información sobre las novedades de la estructura Network. Aprende a crear conexiones, enviar y recibir datos, escuchar conexiones entrantes y descubrir puntos finales en la red.
- 0:45 - Hacer conexiones
La estructura Network simplifica la red de apps. Ofrece funcionalidades como Conectar por nombre y Happy Eyeballs para una resolución de direcciones eficiente. Tiene seguridad TLS incorporada y admite transportes modernos como QUIC. Con la estructura Network, puedes crear una pila de protocolos con una API declarativa. La estructura procesa automáticamente las transiciones de la interfaz de red, los servidores proxy y los estados de conexión, lo que garantiza conexiones sólidas y con capacidad de respuesta. Los objetos NetworkConnection gestionan el ciclo de vida de la conexión, pasando de un estado a otro como “en preparación”, “listo”, “en espera”, “fallido” o “cancelado”. Opcionalmente, puedes supervisar estos estados para actualizar la interfaz.
- 7:22 - Enviar y recibir
El envío y la recepción de datos en la estructura Network son funciones asincrónicas que inician conexiones si es necesario. La función de envío suspende la tarea hasta que se procesan los datos proporcionados. Al recibir datos usando protocolos de transmisión como TLS y TCP, se debe especificar la cantidad de bytes. Pueden producirse errores durante el envío o la recepción, y los errores asociados explican las interrupciones. Para situaciones donde se desconoce el tamaño de los datos, como al cargar imágenes, usa la función de recepción repetidamente con rangos de bytes mínimos y máximos especificados. Para simplificar el procesamiento de mensajes, la estructura introduce un esquema de tipo, longitud, valor (TLV), que codifica y decodifica automáticamente los mensajes, garantizando que se envía exactamente lo que se recibe. En iOS y macOS 26, ahora se pueden enviar y recibir directamente tipos codificables.
- 14:22 - Aceptar conexiones entrantes
NetworkListener permite que tu app acepte conexiones entrantes. Se inicializa con una pila de protocolos y, al invocar la ejecución, inicia una nueva subtarea para cada conexión entrante y las entrega a un controlador para el procesamiento asincrónico de mensajes.
- 16:05 - Buscar otros dispositivos
En iOS 26, la estructura Network presenta NetworkBrowser, que permite a tu app descubrir puntos finales para conexiones de red. NetworkBrowser también puede usar Wi-Fi Aware, una tecnología de red peer-to-peer, o Bonjour para buscar dispositivos o servicios cercanos. Puedes crear un NetworkBrowser para buscar servicios específicos usando descriptores de exploración y, una vez que se descubra un punto final, se puede usar para inicializar una NetworkConnection. Estas nuevas API, diseñadas para la concurrencia estructurada de Swift, hacen que desarrollar apps con conexión a la red sea más fácil y ordenado, ya que eliminan el código repetitivo y brindan la potencia y la flexibilidad de la estructura Network.