0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Swift → TypeScriptをTCPで繋げたい

0
Posted at

はじめに

SwiftとTypeScriptをTCP通信する要件があったので、サンプル実装しました!!

TCP通信とは?

TCPは、2つのプログラムを接続して、データをやり取りするための通信方法です。

今回だと、

Swift
  ⇄ TCP
TypeScript

という接続を作ります。

TCPの特徴はシンプルです。

  • 一度接続すると、その接続を使ってデータを送り続けられる
  • Swift → TypeScript、TypeScript → Swiftの両方向に送れる
  • 文字列だけでなく、JSONや画像などのバイナリも送れる
  • TCP自体は「メッセージ」ではなく、バイト列のストリームとして扱う

今回はまず、

Swift → "こんにちは" → TypeScript

という最小の通信だけを試します。

Swift TypeScript
役割 クライアント サーバー
API NWConnection node:net
動作 接続 → 送信 → 切断 待受 → 受信

今回は次のルールだけ決めます。

127.0.0.1:9000
UTF-8
1メッセージ = 1行(末尾に \n)

今回の成果物

swift_typescript.gif

ディレクトリ

typescript_swift_study/
├── typescript/
│   ├── package.json
│   ├── tsconfig.json
│   └── src/
│       └── server.ts
└── swift/
    ├── Package.swift
    └── Sources/
        └── SocketClient/
            └── main.swift

前提:

macOS
Node.js
Swift 5.9+

通信の流れ

TypeScript

Node.js標準のnetでTCPサーバーを作ります。

import net from "node:net";

const HOST = "127.0.0.1";
const PORT = 9000;

const server = net.createServer((socket) => {
  console.log("connected");

  socket.setEncoding("utf8");

  let buffer = "";

  socket.on("data", (chunk) => {
    buffer += chunk;

    while (buffer.includes("\n")) {
      const index = buffer.indexOf("\n");

      const message = buffer.slice(0, index);
      buffer = buffer.slice(index + 1);

      console.log("received:", message);
    }
  });

  socket.on("end", () => {
    console.log("disconnected");
  });
});

server.listen(PORT, HOST, () => {
  console.log(`listening on ${HOST}:${PORT}`);
});

TCPは「メッセージ」ではなくバイト列のストリームです。

そのため今回は、

こんにちは\n

のように\nを区切りとして使います。

Swift

Network.frameworkのNWConnectionを使います。

import Foundation
import Network

let connection = NWConnection(
    host: "127.0.0.1",
    port: 9000,
    using: .tcp
)

let queue = DispatchQueue(label: "socket")
let semaphore = DispatchSemaphore(value: 0)

connection.stateUpdateHandler = { state in
    switch state {
    case .ready:
        let payload = CommandLine.arguments.dropFirst().first ?? "こんにちは"
        let data = Data((payload + "\n").utf8)

        connection.send(
            content: data,
            completion: .contentProcessed { error in
                if let error {
                    print("send failed:", error)
                } else {
                    print("sent:", payload)
                }

                connection.cancel()
                semaphore.signal()
            }
        )

    case .failed(let error):
        print("connect failed:", error)
        semaphore.signal()

    default:
        break
    }
}

connection.start(queue: queue)

semaphore.wait()

やっていることはこれだけです。

NWConnection作成
↓
TCP接続
↓
ready
↓
"こんにちは\n" を送信
↓
切断

実行

まずTypeScriptを起動します。

cd typescript
npm install
npm start
listening on 127.0.0.1:9000

別ターミナルからSwiftを実行します。

cd swift
swift run SocketClient こんにちは

Swift:

sent: こんにちは

TypeScript:

connected
received: こんにちは
disconnected

これで、

Swift
  ↓ TCP
TypeScript

の最小通信ができました。

今回やったこと

Swift
↓
TCP接続
↓
UTF-8文字列を送信
↓
TypeScriptで受信
↓
切断

次はこの接続をそのまま使って、

TypeScript → Swift
echo
JSON
常時接続
画像

へ広げられます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?