iOS の Network FrameworkでUDPクライアントの受信処理を実装したら、「udp_validate_cksum_internal udp incorrect IPv4-UDP offload checksum」というエラーが出た

# Problem

iOSの[Network Framework](https://developer.apple.com/documentation/network)を使ってUDPクライアントの受信処理を実装したところ、UDP通信ができず以下のようなエラーが表示されることがありました。

```
udp_validate_cksum_internal  udp incorrect IPv4-UDP offload checksum 0xf6dc ulen 1154
udp_validate_cksum_internal  udp incorrect IPv4-UDP offload checksum 0xf5dd ulen 1154
udp_validate_cksum_internal  udp incorrect IPv4-UDP offload checksum 0xf5dd ulen 1154
```

エラーメッセージで検索すると、同じエラーに遭遇した人もいたのですが、解決策は書いてありませんでした。
https://developer.apple.com/forums/thread/665536

参考までにNetwork Frameworkを使った実装を載せます。(一部省略)

```UdpClientImplNW.swift

import Foundation
import Network

/// Network Frameworkを使って実装したバージョン
class UdpClientImplNW {
    private var nwListener: NWListener!
    private let queue = DispatchQueue(label: "UdpClient")

    func bind(port: Int32) {
        let nwPort = NWEndpoint.Port(rawValue: UInt16(port))!
        let params = NWParameters.udp
        params.allowLocalEndpointReuse = true
        let listener = try! NWListener(using: params, on: nwPort)
        nwListener = listener
        listener.stateUpdateHandler = stateDidChange(to:)
        listener.newConnectionHandler = { [unowned self] (connection: NWConnection) in
            connection.start(queue: queue)
            self.receive(on: connection)
        }
        nwListener.start(queue: queue)
    }

    private func stateDidChange(to newState: NWListener.State) {
        print("NWListener stateDidChange: \(newState)")
    }

    private func receive(on connection: NWConnection) {
        connection.receiveMessage(completion: {(data, context, isComplete, error) in
            if let error = error {
                // エラー発生時の処理
            }
            if let data = data {
                // データ受信時の処理
            }

            // 連続して受信する
            self.receive(on: connection)
        })
    }
}

```

# Solution

恐らく、Network Frameworkのバグと思われるため、[robbiehanson/CocoaAsyncSocket](https://github.com/robbiehanson/CocoaAsyncSocket)というライブラリを使って書き直しました。
そうすると、正常にUDPの受信ができ、エラーメッセージも表示されませんでした。

以下がCocoaAsyncSocketを使った実装です。(一部省略）


```UdpClientImpl.swift
import Foundation
import CocoaAsyncSocket

class UdpClientImpl: NSObject {
    private var socket: GCDAsyncUdpSocket!
    private var port: UInt16!

    func bind(port: Int) {
        self.port = UInt16(port)
        socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: DispatchQueue.main)
        do {
            try socket.enableReusePort(true)
        } catch {
            print("Failed to setup socket: \(error)")
        }
        
        do {
            try socket.bind(toPort: UInt16(port))
            try socket.beginReceiving()
        } catch {
            print("Failed to receive: \(error)")
        }
    }
}

extension UdpClientImpl: GCDAsyncUdpSocketDelegate {
    func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress address: Data, withFilterContext filterContext: Any?) {
        // データ受信時の処理
    }

    func udpSocket(_ sock: GCDAsyncUdpSocket, didNotConnect error: Error?) {
        // 接続失敗時の処理
    }

    func udpSocketDidClose(_ sock: GCDAsyncUdpSocket, withError error: Error?) {
        // エラー発生時の処理
    }
}
```