服务器端 Swift:iOS 和 Android 的基本客户端-服务器通信示例

Server Side Swift: basic Client-Server communication example for iOS and Android

学习新技术是一个耗时的过程。 Android 和 Java。 iOS 又是 Swift。我现在面临着需要为 Android 和 iOS 应用程序提供服务器后端的挑战。但是,如果可能的话,我想避免花费大量时间学习一门新语言。据我所知,服务器代码可以用 Java 或 Swift 编写,但 Swift 似乎是一种更简洁的语言,所以这就是我选择使用的原因这条路线。

我想做一个概念验证示例,其中服务器 运行 Swift 能够与 Android 和 iOS 应用程序通信。应用程序发送请求并接收响应。

这个问题和我下面的回答是我对服务器端的介绍Swift。

一个基本示例涉及三件事:

  • A Linux 服务器 运行ning Swift
  • 一个 Android 应用程序
  • 一个 iOS 应用程序

本次回答的重点是Swift服务器。

Linux服务器运行宁Swift

这些说明基于名为 Server-Side Swift 的免费 Udacity 课程的第一单元。我建议把整件事都拿走。从那以后一直有更新,但它解释得很慢很清楚。

1。通过 ssh 登录到您的 Linux 服务器

在此示例中,我们将使用具有静态 IP 的 VPS。如果你没有,你可以从很多地方得到一个。 LowEndBox 有便宜的选择。我在这个例子中使用 Ubuntu Linux。您应该会收到服务器的 IP 地址以及根密码。

根据您 VPS 安装的内容,您可以 want/need 安装以下依赖项。

  • sudo apt-get install nano(文本编辑器,比vim更直观)
  • sudo apt-get install git

2。安装 swiftenv

这将帮助您下载 Swift 服务器和管理不同的版本环境。 installation directions 非常清楚。选择 Git 选项。

git clone https://github.com/kylef/swiftenv.git ~/.swiftenv

如果您没有安装 gitcurl,您需要先安装它们:

  • sudo apt-get install curl
  • sudo apt-get install git

如说明所述,您应该将这些行添加到 ~/.bash_profile 文件的末尾(或者在我的情况下是 ~/.bashrc)。

# swiftenv
export SWIFTENV_ROOT="$HOME/.swiftenv"
export PATH="$SWIFTENV_ROOT/bin:$PATH"
eval "$(swiftenv init -)"

这将允许您随时从命令行使用 swiftenv。要应用设置,请使用 . ~/.bash_profile(或 . ~/.bashrc)从命令行重新加载 bash 文件。

3。安装 Swift

您可以直接 download Swift,但使用 swiftenv 更容易。

swiftenv install 4.0.2

您可以将 4.0.2 替换为您想要的任何 Swift 版本。检查当前版本 here.

您现在应该可以 Swift 运行宁

swift

希望能给你这样的东西

Welcome to Swift version 4.0.2 (swift-4.0.2-RELEASE). Type :help for assistance.
  1> 

您可以在此处输入 Swift 代码。玩完游戏后,输入 :exit 退出。

如果出现错误,可能是您需要安装更多的依赖项。一路上这件事发生在我身上好几次。只是 Google 错误,然后使用 sudo apt-get install.

安装任何你需要的东西

4。创建我们的 Swift 服务项目

这是我们将放置与我们的 Android 和 iOS 应用程序通信的实际 Swift 服务器代码的地方。

为项目创建一个目录并将cd放入其中。

mkdir MyFirstSwiftServer
cd MyFirstSwiftServer

在命令行中使用Swift Package Manager来设置我们的新项目。

swift package init --type executable

5。为 Swift

添加 Kitura 网络框架

Kitura 框架提供了使客户端-服务器通信成为可能的工具。 Kitura 来自 IBM。还有很多其他的(看一个comparison). Perfect is a popular one, but the only tutorial I watched was hard to follow. Anyway, I'm choosing Kitura for now because the Udacity series太容易理解了。

在我们刚刚创建的 MyFirstSwiftServer 目录中打开 Package.swift 文件。

nano Package.swift

编辑它以包含 Kitura 依赖项和目标。您可以找到最新版本 here.

// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "MyFirstSwiftServer",
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        .package(url: "https://github.com/IBM-Swift/Kitura.git", from: "2.1.0")
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages which this package depends on.
        .target(
            name: "MyFirstSwiftServer",
            dependencies: ["Kitura"]),
    ]
)

这也是您要包含 SwiftlyJSON, but at the time of this writing there is a bug 以阻止它工作的地方。不过,我们的最小示例不需要它。

6.编写服务器代码

打开 main.swift 文件

nano Sources/MyFirstSwiftServer/main.swift

然后粘贴以下代码。这仅对 Udacity 课程第 1 课第 11 部分中使用的代码稍作修改。

import Kitura

// Create a new router
let router = Router()

// Handle HTTP GET requests to /
router.get("/") {
    request, response, next in
    response.send("Hello, Client!")
    next()
}

// Add an HTTP server and connect it to the router
Kitura.addHTTPServer(onPort: 8090, with: router)

// Start the Kitura runloop (this call never returns)
Kitura.run()

请注意,我们使用了端口 8090。我们将在连接到服务器时使用它。

7。测试服务器

在您的项目根文件夹中,使用

构建项目
swift build

然后运行编译后的可执行文件

./.build/debug/MyFirstSwiftServer

您可以使用网络浏览器进行测试,然后转到

http://93.184.216.34:8090   // replace 93.184.216.34 with your vps ip address

你应该看看

Hello, Client!

太棒了!服务器正在运行。


Android 客户

1。布局

在 Android Studio 中创建以下布局

2。请求互联网权限

将以下行添加到清单中。

<uses-permission android:name="android.permission.INTERNET" />

对于Android 9+你还需要。 (请注意,对于生产应用程序,您应该使用 https 连接而不是 http 连接。)将以下内容添加到清单中:

<application
    android:usesCleartextTraffic="true"
    ...
    >

3。代码

复制代码。其中大部分改编自 Android AsyncTask HTTP GET request Tutorial。不要忘记用您的服务器替换 ip 地址。

public class MainActivity extends AppCompatActivity {

    // replace 93.184.216.34 with your vps server ip address
    private static final String SERVER = "http://93.184.216.34:8090/";

    private TextView tvServerResponse;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvServerResponse = findViewById(R.id.textView);
        Button contactServerButton = findViewById(R.id.button);
        contactServerButton.setOnClickListener(onButtonClickListener);
    }

    View.OnClickListener onButtonClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            HttpGetRequest request = new HttpGetRequest();
            request.execute();
        }
    };

    public class HttpGetRequest extends AsyncTask<Void, Void, String> {

        static final String REQUEST_METHOD = "GET";
        static final int READ_TIMEOUT = 15000;
        static final int CONNECTION_TIMEOUT = 15000;

        @Override
        protected String doInBackground(Void... params){
            String result;
            String inputLine;

            try {
                // connect to the server
                URL myUrl = new URL(SERVER);
                HttpURLConnection connection =(HttpURLConnection) myUrl.openConnection();
                connection.setRequestMethod(REQUEST_METHOD);
                connection.setReadTimeout(READ_TIMEOUT);
                connection.setConnectTimeout(CONNECTION_TIMEOUT);
                connection.connect();

                // get the string from the input stream
                InputStreamReader streamReader = new InputStreamReader(connection.getInputStream());
                BufferedReader reader = new BufferedReader(streamReader);
                StringBuilder stringBuilder = new StringBuilder();
                while((inputLine = reader.readLine()) != null){
                    stringBuilder.append(inputLine);
                }
                reader.close();
                streamReader.close();
                result = stringBuilder.toString();

            } catch(IOException e) {
                e.printStackTrace();
                result = null;
            }

            return result;
        }

        protected void onPostExecute(String result){
            super.onPostExecute(result);
            if (result == null) return;
            tvServerResponse.setText(result);
        }
    }
}

4。测试 Android 应用程序

运行 应用程序。按下按钮,希望你会看到

成功! Android.

上的客户端-服务器通信

iOS 客户

1。布局

在Xcode中创建如下布局

2。禁用 App Transport Security

这对于生产应用来说并不理想,但它会帮助我们避免 ,因为我们的 VPS 目前仅支持未加密的 http 连接。

将以下密钥添加到您的 Info.plist 文件中。

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

3。代码

有关在 Swift 中发出 HTTP 请求的更多信息,请参阅 this Q&A

import UIKit

class ViewController: UIViewController {

    // replace 93.184.216.34 with your vps server ip address
    let server = "http://93.184.216.34:8090"

    @IBOutlet weak var serverResponseLabel: UILabel!

    @IBAction func sendRequestButtonTappled(_ sender: UIButton) {

        guard let url  = URL(string: server) else {return}

        // background task to make request with URLSession
        let task = URLSession.shared.dataTask(with: url) {
            (data, response, error) in

            if let error = error {
                print(error)
                return
            }

            guard let data = data else {return}
            guard let dataString = String(data: data, encoding: String.Encoding.utf8) else {return}

            // update the UI if all went OK
            DispatchQueue.main.async {
                self.serverResponseLabel.text = dataString
            }
        }

        // start the task
        task.resume()
    }
}

4。测试 iOS 应用程序

运行 应用程序。按下按钮,希望你会看到

成功! iOS.

上的客户端-服务器通信