服务器端 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
如果您没有安装 git
或 curl
,您需要先安装它们:
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.
上的客户端-服务器通信
学习新技术是一个耗时的过程。 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
如果您没有安装 git
或 curl
,您需要先安装它们:
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+你还需要
<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
这对于生产应用来说并不理想,但它会帮助我们避免
将以下密钥添加到您的 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.
上的客户端-服务器通信