SwiftでUDP通信を行う

# はじめに
　SwiftでUDPで通信を行う機会があり、実装の仕方やUDPとTCPとの違いについて復習もかねてまとめました。
　UDPって何？という方やTCPとの違いがあまりわかっていないという方のお役に立てれば幸いです。

# 目次
[1.UDPとは？](##1-UDPとは？)
[2.UDPとTCPの違い](##2-UDPとTCPの違い)
[3.UDP送信の実装](##3-UDP送信の実装)
[4.受信して確認してみる](##4-受信して確認してみる)
[5.参考文献](##5-参考文献)

## 1.UDPとは？
UDPとはUser Datagram Protocolの略です。
OSI参照モデルの第4層トランスポート層で動作するプロトコルです。
通信品質を担保せず、投げっぱなしのため、受信してみないと受信できるかの確認ができません。しかし無駄な通信を行わないため、通信速度を向上させリアルタイムな通信環境を確立させることが可能です。

## 2．UDPとTCPの違い
UDPとTCPの違いについて表にまとめてみました。
UDPはコネクションレス型で信頼性は低いですが、信頼性を必要とせず高速で通信がしたいときに使用します。
逆にTCPは転送速度は低速ですが、コネクション型で信頼性が高く確実に送信したいときに使用します。
どちらが優れているというのではなく、何を優先するかによってTCPとUDPを使い分けます。
|  プロトコル |        TCP        |        UDP         |
|:--------------|:-----------------:|:------------------:|
| 転送速度      |　低速　|　高速　|
| 信頼性        |　高い　| 低い       |
| 通信方式      |　　コネクション型　　|　コネクションレス型　|
| 上位プロトコル|HTTP,Telnt,FTP,POPなど|DNS,NTP,DHCP,SNMPなど|
| 主な用途    　|Webの閲覧、メールの送受信など|音声通話、動画ストリーミングなど|

## 3．UDP送信の実装
実際にSwiftを使ってUDP送信の実装をしてみます。macOSはMontereyでXcode 13を使用しています。
SwiftUIを使ってConnectボタンを押して接続し、Sendボタンを押すと「あいうえお」を送信するコードを作成しました。
```swift
import SwiftUI
import Network

struct ContentView: View {
    @State var host: NWEndpoint.Host = "127.0.0.1"
    @State var port: NWEndpoint.Port = 12345
    @State var connection: NWConnection?
    
    var body: some View {
        VStack{
            Button("Connect") {
                connect()
            }
            Button("Send") {
                send("あいうえお".data(using: .utf8)!)
            }
        }
    }
    func send(_ payload: Data) {
        connection!.send(content: payload, completion: .contentProcessed({ sendError in}))
    }
    func connect() {
        connection = NWConnection(host: host, port: port, using: .udp)
        connection!.start(queue: .global())
    }
}
```
コードの解説をします。
### アドレス・ポートの指定
最初に接続先のアドレスやポート番号を指定します。
```swift
@State var host: NWEndpoint.Host = "127.0.0.1"
@State var port: NWEndpoint.Port = 12345
@State var connection: NWConnection?
```
### UIの表示
ここはUIに表示するコードで、画面のようにConnectボタンとSendボタンの表示をします。
Connectボタンを押すとアドレスやポート番号で指定した接続先と通信を開始します。
通信開始後、Sendボタンを押すと「あいうえお」というメッセージを送信します。
```swift
VStack{
       Button("Connect") {
           connect()
       }
       Button("Send") {
           send("あいうえお".data(using: .utf8)!)
       }
}
```
<img src= https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871987/5125b555-fd07-6e48-06d1-26abd2db1a3f.png width=50%>

### 送信
送信ボタンを押すとこの関数の中に入ります。ここでメッセージの送信をしています。
通信をせずに送信してしまうとConnectionの値がnilのため、エラーが発生します。
```swift
func send(_ payload: Data) {
    connection!.send(content: payload, completion: .contentProcessed({ sendError in}))
}
```
### 通信
Connectボタンを押すとこの関数に入ります。ここでは、NWConnectionの初期化を行います。
最初に指定したアドレスやポート番号、接続方法などを初期化しています。
```swift
func connect() {
        connection = NWConnection(host: host, port: port, using: .udp)
        connection!.start(queue: .global())
    }
```
## 4．受信して確認してみる
先ほど作成したUDP送信をターミナルでUDPサーバーを立ち上げて受信できるか確認してみます。
ターミナルで以下の一行を入力することでUDPサーバーを立ち上げることができます。
```
$ nc -u -l 12345
```
![スクリーンショット 2022-09-28 14.37.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871987/8b428323-9ef5-8311-f8b4-d6be7d7bc842.png)
無事に受信することができました。

## 5．参考文献
[TCPとUDPの違いとは？　～Ethernet接続におけるオーバーヘッド削減ノウハウ～](https://hldc.co.jp/blog/2019/07/11/2819/)
[UDPでiPhoneとMacでソケット通信【C言語】](https://101010.fun/programming/iphone-c-udp.html)
[【Swift】NWConnectionの基本的な使い方をエンジニアが解説](https://www.radical-dreamer.com/programming/nwconnection-swift/)
[NWConnection | Apple Developer Documentation](https://developer.apple.com/documentation/network/nwconnection/)