android 应用加密

重点 (Top highlight)

In this tutorial, we’ll build an encrypted chat/messaging example app for Android. To do this, we will combine both Stream Chat and Virgil Security platforms. Stream and Virgil make it easy to build a solution with excellent security by combining all of the features you would expect as a developer when creating a messaging app.

在本教程中,我们将为Android构建一个加密的聊天/消息示例应用程序。 为此,我们将结合Stream Chat和Virgil Security平台。 通过结合使用您在创建消息传递应用程序时作为开发人员的所有期望功能,Stream和Virgil可以轻松构建具有出色安全性的解决方案。

These two services allow developers to integrate chat that is zero knowledge to your backend or Stream. The example app embeds Virgil Security’s eThree Kit — a secure encrypted messaging platform — with Stream Chat’s Android components.

这两项服务使开发人员可以将对您零知识的聊天集成到您的后端或流中。 示例应用程序嵌入 维吉尔安全 eThree套件 —安全的加密消息传递平台 -使用Stream Chat的Android组件。

Note that all source code for this example, Android app is available on GitHub. Additionally, before jumping into this tutorial, I recommend checking out the Stream Chat Android tutorial, which will walk you through how to implement Stream Chat from a high-level overview.

请注意,此示例Android应用程序的所有源代码都可以在GitHub上找到 。 另外,在进入本教程之前,我建议您阅读Android的Stream Chat教程 ,它将从较高的概述中逐步指导您如何实现Stream Chat。

什么是端到端加密消息? (What Is End-To-End Encrypted Messaging?)

End-to-end encrypted messaging means that the users within that specific chat can only read messages sent between two people. To enable this, the messages that are sent are encrypted before leaving a user’s device, and can only be decrypted by the intended recipient (end-user).

端到端加密消息传递意味着特定聊天中的用户只能阅读两个人之间发送的消息。 为此,发送的消息在离开用户设备之前已加密,并且只能由预期的接收者(最终用户)解密。

Virgil Security is a vendor that allows developers to create end-to-end encryption via public/private key technology through the use of their robust and secure encrypted messaging service. With Virgil’s Android SDK, developers can securely create, store, and provide robust end-to-end encryption.

Virgil Security是一家供应商,允许开发人员通过使用其健壮且安全的加密消息传递服务,通过公用/专用密钥技术创建端到端加密。 借助Virgil的Android SDK,开发人员可以安全地创建,存储和提供强大的端到端加密。

During this tutorial, we will learn how to build a Stream Chat app that uses Virgil’s encryption/decryption platform to prevent anyone except the intended parties from reading messages. No one in your company, nor any cloud provider you use, can read these messages. In essence, even if a malicious person gained access to the database containing the messages, that person would only see encrypted text, called ciphertext.

在本教程中,我们将学习如何构建一个使用Virgil的加密/解密平台的Stream Chat应用程序,以防止除目标用户之外的任何人阅读消息。 您公司中的任何人,或者您使用的任何云提供商,都无法阅读这些消息。 本质上,即使恶意人员获得了访问包含消息的数据库的权限,该人员也只会看到称为密文的加密文本。

构建加密的聊天消息应用程序 (Building an Encrypted Chat Messaging Application)

To build this app, we’ll mostly rely on two libraries, Stream Chat Android and Virgil Security for Kotlin. Our outcome will encrypt text on the device before sending a message. Decryption and verification will both happen in the receiver’s device. Stream’s Messaging API will only see ciphertext, ensuring our user’s data is never seen by anyone else, including us.

要构建此应用,我们将主要依靠两个库,即Stream Chat Android和Virgil Security for Kotlin。 我们的结果将在发送消息之前对设备上的文本进行加密。 解密和验证都将在接收方的设备中进行。 Stream的Messaging API仅能看到密文,以确保包括我们在内的其他任何人都不会看到我们用户的数据。

To accomplish this, the app performs the following steps:

为此,该应用程序执行以下步骤:

  1. A user authenticates with your backend.
    用户向您的后端进行身份验证。
  2. The user’s app requests a Stream auth token and API key from the backend. The Android app creates a Stream Chat Client for that user.

    用户的应用程序从后端请求流身份验证令牌和API密钥。 Android应用会为该用户创建一个Stream Chat Client 。

  3. The user’s app requests a Virgil auth token from the backend and registers with Virgil. This generates their private and public key. The private key is stored locally, and the public key is stored in Virgil.
    用户的应用程序从后端请求Virgil身份验证令牌,并向Virgil注册。 这将生成其私钥和公钥。 私钥存储在本地,而公钥存储在Virgil中。
  4. Once the user decides who they want to chat with the app creates and joins a Stream Chat Channel.

    用户决定要与该应用聊天的对象后,即可创建并加入流聊天频道 。

  5. The app asks Virgil for the receiver’s public key.
    该应用程序向Virgil询问接收者的公共密钥。
  6. The user types a message and sends it to Stream. Before sending, the app passes the receiver’s public key to Virgil to encrypt the message. The message is relayed through Stream Chat to the receiver. Stream receives ciphertext, meaning they can never see the original message.
    用户键入一条消息并将其发送到Stream。 在发送之前,该应用将接收者的公钥传递给Virgil来加密消息。 该消息通过流聊天中继到接收者。 Stream收到密文,这意味着他们永远看不到原始消息。
  7. The receiving user decrypts the sent message using Virgil. When the message is received, the app decrypts the message using the Virgil and this is passed along to Stream’s UI components. Virgil verifies the message is authentic by using the sender’s public key.
    接收用户使用Virgil解密发送的消息。 收到消息后,应用程序将使用Virgil对消息进行解密,并将消息传递到Stream的UI组件。 Virgil使用发件人的公钥验证邮件的真实性。

While this looks complicated, Stream and Virgil do most of the work for us. We’ll use Stream’s out of the box UI components to render the chat UI and Virgil to do all of the cryptography and key management. We simply combine these services.

尽管这看起来很复杂,但Stream和Virgil为我们完成了大部分工作。 我们将使用Stream的现成UI组件来呈现聊天UI,而Virgil将使用所有的加密和密钥管理。 我们只是将这些服务结合在一起。

The code is split between the Android frontend contained in the android directory, and the Express (Node.js) backend is found in the backend directory. See the README.md in each directory to see installing and running instructions. If you'd like to follow along with running code, make sure you get both the backend and android running before continuing.

该代码是Android之间的分裂前端包含在android目录,而快递(Node.js的)后端在发现backend目录。 请参阅每个目录中的README.md以查看安装和运行说明。 如果您想继续执行代码,请确保在继续运行之前先运行backendandroid

Let’s walk through and look at the important code needed for each step.

让我们来看一下每个步骤所需的重要代码。

先决条件 (Prerequisites)

Basic knowledge of Android (Kotlin) and Node.js is required to follow this how-to tutorial.

要学习此入门指南,需要具备Android(Kotlin)和Node.js的基础知识。

Note that this secure messaging app is intended only to run locally on your machine, and we will not be covering how to deploy the example app to iOS or Android app stores.

请注意,此安全消息传递应用程序仅旨在在您的计算机上本地运行,我们将不介绍如何将示例应用程序部署到iOS或Android应用程序商店。

We use Anko to simplify our asynchronous code. Please note this library was recently deprecated. There are also likely bugs in our async implementation. However, we chose to keep the noise to a minimum in this tutorial by leveraging Anko and keeping async simple. Please use best practices for asynchronous code.

我们使用Anko来简化异步代码。 请注意,该库最近已弃用 。 我们的异步实现中也可能存在错误。 但是,在本教程中,我们选择通过利用Anko并使异步保持简单来将噪声降至最低。 请对异步代码使用最佳做法。

You will need an account with Stream and Virgil. Once you’ve created your accounts, you can place your credentials in backend/.env if you'd like to run the code. You can use backend/.env.example as a reference for what credentials are required. You also need to place your Stream API key in MainActivity.kt:60.

您将需要具有Stream和Virgil的帐户。 创建帐户后,如果您想运行代码,则可以将凭据放在backend/.env 。 您可以使用backend/.env.example作为所需凭据的参考。 您还需要将Stream API密钥放在MainActivity.kt:60

步骤0。设置后端 (Step 0. Setup the Backend)

For our Android frontend to interact with Stream and Virgil, the application provides three endpoints:

为了使我们的Android前端与Stream和Virgil进行交互,该应用程序提供了三个端点:

  • POST /v1/authenticate: This endpoint generates an auth token that allows the Android app to communicate with /v1/stream-credentials and /v1/virgil-credentials. To keep things simple, this endpoint allows the client to be any user. The frontend tells the backend who it wants to authenticate as. In your application, this should be replaced with your API's authentication endpoint.

    POST /v1/authenticate :此端点生成一个auth令牌,该令牌允许Android应用与/v1/stream-credentials/v1/virgil-credentials 。 为简单起见,此端点允许客户端成为任何用户。 前端告诉后端它想作为谁进行身份验证。 在您的应用程序中,应将其替换为您API的身份验证端点。

  • POST /v1/stream-credentials: This returns the data required for the Android app to communicate with Stream. In order return this info we need to tell Stream this user exists and ask them to create a valid auth token:

    POST /v1/stream-credentials :这将返回Android应用程序与Stream通信所需的数据。 为了返回此信息,我们需要告诉Stream该用户存在,并要求他们创建有效的身份验证令牌:

The response payload has this shape:

响应有效负载具有以下形状:

  • apiKey is the stream account identifier for your Stream instance. Needed to identify what account your frontend is trying to connect with.

    apiKey是您的Stream实例的流帐户标识符。 需要确定您的前端试图连接哪个帐户。

  • token JWT token to authorize the frontend with Stream.

    token JWT令牌,用于使用Stream授权前端。

  • user: This object contains the data that the frontend needs to connect and render the user's view.

    user :此对象包含前端连接和呈现用户视图所需的数据。

  • POST /v1/virgil-credentials: This returns the authentication token used to connect the frontend to Virgil. We use the Virgil Crypto SDK to generate a valid auth token for us:

    POST /v1/virgil-credentials :这将返回用于将前端连接到Virgil的身份验证令牌。 我们使用Virgil Crypto SDK为我们生成有效的身份验证令牌:

In this case, the frontend only needs the auth token.

在这种情况下,前端只需要auth令牌。

步骤1.用户通过后端进行身份验证 (Step 1. User Authenticates With Backend)

First, we log in to a user. To keep things simple we’ll just have an empty form that lets you log in with any name:

首先,我们登录到用户。 为简单起见,我们将使用一个空表格来使用任何名称登录:

Image for post

This is a simple form that takes any arbitrary name, effectively allowing us to log in as anyone. We set this up in our MainActivity:

这是一种简单的形式,可以使用任意名称,有效地允许我们以任何人身份登录。 我们在MainActivity

And the layout:

以及布局:

When we submit the form, we sign into our backend, get a Stream and Virgil frontend auth token, generate our private key, and register with Virgil, then start our next activity. We’ll look at each of these in turn.

提交表单时,我们登录到后端,获取Stream和Virgil前端身份验证令牌,生成私钥,并在Virgil中注册,然后开始下一个活动。 我们将依次研究每个。

Let’s see our sign in and token generation:

让我们看看我们的登录和令牌生成:

Since our backend (see Step 1) does the token generation, these are simple REST calls. The tokens returned are frontend auth tokens, which allow our client to talk to Stream and Virgil directly. Besides returning a list of users, we no longer need our backend to do any work.

由于我们的backend (请参阅步骤1)执行令牌生成,因此这些都是简单的REST调用。 返回的令牌是前端身份验证令牌,使我们的客户端可以直接与Stream和Virgil进行对话。 除了返回用户列表之外,我们不再需要后端进行任何工作。

Now that we have our frontend tokens, let’s generate our private keys and register our public keys with Virgil:

现在我们有了前端令牌,让我们生成私有密钥并向Virgil注册我们的公共密钥:

Virgil’s client is called eThree. We initialize an EThree instance and register. This call generates a private key and stores it on the device and sends our public key to Virgil. If we get a RegistrationException, we have already registered this user. Keep in mind, and you cannot log into the same user on a different device since we're not sharing the private key with the other device! This is possible, but out of scope for this tutorial. If you'd like to accomplish this, see Virgil's documentation.

Virgil的客户称为eThree 。 我们初始化一个EThree实例并注册。 该调用将生成一个私钥并将其存储在设备上,并将我们的公钥发送给Virgil。 如果收到RegistrationException ,则我们已经注册了该用户。 请注意,由于我们不与其他设备共享私钥,因此您无法在其他设备上登录同一用户! 这是可能的,但是超出了本教程的范围。 如果您想完成此操作,请参阅Virgil的文档 。

Now that we have our tokens and registration let’s find a user to chat with!

现在我们有了令牌和注册,让我们找到一个可以聊天的用户!

步骤2:列出使用者 (Step 2: List users)

To keep things simple, we’ll get all registered users from our backend and display them in a simple list view:

为简单起见,我们将从后端获取所有注册用户,并将其显示在简单的列表视图中:

Here is the activity:

这是活动:

And the layout:

以及布局:

We make an API call via BackendService.getUsers and filter the logged-in user out. We add the response to a simple ArrayAdapter and display our results in a ListView. When a user clicks on a list item, we start a ChannelActivity, which is a 1:1 chat channel.

我们通过BackendService.getUsers进行API调用,并过滤掉登录的用户。 我们将响应添加到简单的ArrayAdapter并将结果显示在ListView 。 当用户单击列表项时,我们将启动ChannelActivity ,这是一个1:1聊天频道。

步骤3:建立私人1:1频道 (Step 3: Create a Private 1:1 Channel)

First, we need to create our channel for our private chat. Let’s look at our activity and layout:

首先,我们需要为我们的私人聊天创建频道。 让我们看看我们的活动和布局:

And the layout:

以及布局:

We use off the shelf Stream UI components with two slight variations. First, we hook in a custom EncryptedMessageInputView, which allows us to encrypt a message before sending it. We also hook in a custom EncryptedMessageViewHolderFactory, which allows message decryption (we'll look at this in a bit). The essential bits start inside of doAsync. First, we look up the other user's public key. This let's use encrypt our messages and verify their messages are authentic. Next, we create a channel in Stream via .query. Once then channel is created, we load messages. Before we look at how we load messages, we need to send a message first.

我们使用现成的Stream UI组件有两个微小的变化。 首先,我们挂钩一个自定义的EncryptedMessageInputView ,它允许我们在发送消息之前对其进行加密。 我们还挂钩了一个自定义的EncryptedMessageViewHolderFactory ,它允许消息解密(稍后我们将对此进行介绍)。 基本位在doAsync内部开始。 首先,我们查找其他用户的公钥。 让我们使用加密消息并验证其消息是真实的。 接下来,我们通过.query在Stream中创建一个通道。 创建通道后,我们便会加载消息。 在查看如何加载消息之前,我们需要先发送一条消息。

步骤4:发送加密的消息 (Step 4: Sending an Encrypted Message)

Let’s look at EncryptedMessageInputView, which is bound in the layout and configured in our activity. Here is the code:

让我们看一下EncryptedMessageInputView ,它绑定在布局中并在我们的活动中配置。 这是代码:

We override Stream’s MessageInputView and simply decrypt the message before sending it. MessageInputView calls prepareMessage before sending it to the API, so we override this and encrypt before sending the message along.

我们重写Stream的MessageInputView并在发送之前简单地解密消息。 MessageInputView在将其发送到API之前会调用prepareMessage ,因此我们将其覆盖并加密,然后再发送消息。

Please note that updating a message does not utilize this method, so be aware if you want to support edit functionality. You can consider building your own MessageInputView. For brevity, we won't go there in this tutorial.

请注意,更新消息不会使用此方法,因此请注意是否要支持编辑功能。 您可以考虑构建自己的MessageInputView 。 为简便起见,本教程中不会去那里。

步骤5:查看消息 (Step 5: Viewing Messages)

Since all of our messages in Stream our now ciphertext, we need to decrypt them before displaying. To hook into Stream’s UI components, we bind via binding.messageList.setViewHolderFactory(EncryptedMessageViewHolderFactory(eThree)). With our custom factory, we can initialize a custom decryption object for each message:

由于我们Stream中的所有消息都是我们现在的密文,因此我们需要在显示之前解密它们。 为了连接到Stream的UI组件,我们通过binding.messageList.setViewHolderFactory(EncryptedMessageViewHolderFactory(eThree))绑定。 使用我们的自定义工厂,我们可以为每条消息初始化一个自定义解密对象:

This factory checks if we have a message type (vs. another type such as a date separator) and initializes our EncryptedMessageViewHolder. Let's look take a look:

该工厂检查我们是否具有消息类型(相对于其他类型,例如日期分隔符),并初始化EncryptedMessageViewHolder 。 让我们看一下:

First, we check if we have a regular message, and if we do, we decrypt it. We copy our message object to avoid mutating the original version (Stream caches this, and we’ll mess things up if we manipulate that). With that copy, we check if the message is ours or theirs. In our case, we know how to decrypt directly since we created it. If it’s theirs, we need to look up their public key to verify the message. We pass this to Virgil and do our decryption.

首先,我们检查是否有常规消息,如果有,则将其解密。 我们复制消息对象以避免更改原始版本(Stream对此进行缓存,如果对其进行操作,将会使事情搞砸)。 使用该副本,我们检查邮件是我们的还是他们的。 在我们的案例中,自创建以来,我们就知道如何直接解密。 如果是他们的,我们需要查找他们的公钥以验证消息。 我们将此传递给Virgil并进行解密。

Putting these last steps together, we’ll see our final product:

将这些最后的步骤放在一起,我们将看到最终产品:

最后的想法 (Final Thoughts)

And that’s it. We now have a private and extremely secure end-to-end encrypted messaging app built for Android with Stream Chat and Virgil Security. You should have a full understanding of the basics of end-to-end encryption using Stream Chat and Virgil Security, along with a fundamental understanding of how the E2EE process works when implemented with Android, Virgil, and Stream Chat.

就是这样。 w ^ e现在拥有一个专用于Android的私有且极其安全的端到端加密消息应用程序,具有 即时通讯 维吉尔安全 您应该全面了解使用Stream Chat和Virgil Security进行的端到端加密的基础知识,以及对在使用Android,Virgil和Stream Chat实施时E2EE流程如何工作的基本理解。

If you want to take it a step further, Stream Chat offers several resources to help you get to the next level with your Android chops. Check out the links below:

如果您想更进一步,Stream Chat提供了多种资源来帮助您将Android排行榜提升到一个新的水平。 检查下方的链接:

  • Building an Encrypted, HIPAA Compliant Chatbot

    构建符合HIPAA标准的加密聊天机器人

  • Build HIPAA Compliant Chat

    建立符合HIPAA的聊天

  • Android Chat Bubbles: Building iOS Style Chat in Android

    Android聊天气泡:在Android中构建iOS样式聊天

Happy coding, and as always, please feel free to drop any thoughts or questions in the comments below.

祝您编程愉快,并且一如既往,请随时在下面的评论中提出任何想法或问题。

Originally published on The Stream Blog at https://getstream.io/blog/encrypted-messaging-app-android/.

最初发布在The Stream Blog上, 网址 https://getstream.io/blog/encrypted-messaging-app-android/

翻译自: https://medium.com/swlh/encrypted-messaging-app-android-c57f14a180cb

android 应用加密

http://www.taodudu.cc/news/show-3195451.html

相关文章:

  • mac IntelliJ IDEA 快捷键总结
  • php cgi远程控制,php cgi远程任意代码执行漏洞
  • linux系统virtualenv创建虚拟环境提示command not found
  • 通过J-Flash回读取芯片的固件程序
  • 加--with-x编译vim时报错 configure: error: could not configure X
  • VirtIO-GPU环境搭建与应用
  • V 神呼吁宽大处理!以太坊开发者 Virgil Griffith 被判入狱 63 个月
  • asp数据库操作大全 [网站网页]
  • JavaWeb frontTools / fronttool / web design
  • flash知识
  • Flex3与Flash使用总结
  • Flash与Flex3的配合,特总结一下心得体会
  • Flash与Flex3结合学习心得体会
  • Flash Builder 4beta2 版中的新特性
  • Flash与Flex3的配合
  • [转]Flash与Flex3结合学习心得体会_Rich.Lee的网路历程_百度空间(转载)
  • [转]Flex加载swf的几个要点
  • Flex加载swf的几个要点
  • 专为多设备、多分辨率应用而设计
  • Flash动画学习指引六:操作动作补间
  • 用Adobe Flash Professional CS6创建一个iOS应用程序
  • html 输入数字冒泡,Html5 冒泡排序演示
  • 伺服驱动器和电机控制
  • 第一,永远不要跟银行借钱;第二,永远不要向民间借贷;第三,量力而行(转)...
  • 李彦宏上五环被交警调查?近距离探测“无人车”后真相大白
  • 扔掉代码表!用RNN“破解”摩斯电码
  • (二)从何改变
  • 就不信邪张一鸣
  • 【日常篇】005_用Python制作《太空大战》
  • 单进程程序的守护脚本示例

android 应用加密_加密的短信应用程序android相关推荐

  1. wsdl互联网短信接口_中国移动推出短信小程序

    小程序赛道要逆天了,继微信小程序,百度小程序,支付宝小程序,头条小程序,360PC小程序之后,中国移动宣布也将进入小程序赛道,推出短信小程序,覆盖生活吃穿住行所有场景! 了解到,所谓的短信小程序其实就 ...

  2. wsdl互联网短信接口_中国移动推出短信小程序,逆袭机会在哪里?

    小程序赛道要逆天了,继微信小程序,百度小程序,支付宝小程序,头条小程序,360PC小程序之后,中国移动宣布也将进入小程序赛道,推出短信小程序,覆盖生活吃穿住行所有场景! 了解到,所谓的短信小程序其实就 ...

  3. 安卓手机超过30天短信恢复_免费恢复短信记录安卓(教你Android手机短信恢复技巧)...

    随着手机的不断更新换代,现在的手机短信统一存储在了手机中的一种sqlite格式的数据库文件中,想要恢复手机短信,首先需要获取手机的root权限,这是手机的最高权限,获取权限伴随着风险,如果不太了解相关 ...

  4. 为了更有效率地偷钱,Android root木马开始试水短信扣费诈骗

    本文讲的是 为了更有效率地偷钱,Android root木马开始试水短信扣费诈骗, 自2006年9月以来,我们就一直在监控Google Play商店有关Ztorg木马的各种新变异版本 ,到目前为止,我 ...

  5. android不调用系统发送短信,android之两种方式调用短信发送接口

    释放双眼,带上耳机,听听看~! 相信很多程序员在开发程序的时候都会遇到短信调用端口的情况,今天是技术狗小编为大家带来的关于android之两种方式调用短信发送接口,希望对你学习这方面知识有帮助! an ...

  6. android短信功能裁剪,Android短信发送功能实现技巧分享

    如现在启动一模拟器id 号为5554,运行cmd telnet localhost 5554 输入help 可以看到很多用于模拟器中的功能命令 gsm call 134343434   // 便是呼叫 ...

  7. Android 短信模块分析(四) MMS之短信的发送与接收

     MMS之短信的发送与接收分析: 一.信息发送: com.android.mms.data.WorkingMessage.java 类 send()函数: public void send() { . ...

  8. Android从普通发送和接收短信到对短信进行拦截

    概述: 说实话,关于Android中对短信的一些相关操作是一个比较入门的东西.那我现在还要来写这一篇博客的原因只是因为现在开发中有相关内容,而又想将这些东西分享给更多的人来学习,同时在以后对Andro ...

  9. Android内容提供器的应用,基于Android的智能终端应用防护系统短信过滤子模块的设计与实现...

    摘要: 智能终端随着3G业务的推广而普及,在各种平台的竞争中,Android逐渐占据了主流,谷歌学习苹果的应用商店模式,推出了自己的应用商城.面对应用市场的繁荣,用户的终端安装了形形色色的应用,许多安 ...

最新文章

  1. 技术图文:02 创建型设计模式(下)
  2. JAVA实现斐波那契数列问题(《剑指offer》)
  3. 深入学习Java8 Lambda (default method, lambda, function reference, java.util.function 包)
  4. mysql cluster 读写分离_mysql数据库集群实现高可用读写分离_一点课堂(多岸学院)...
  5. 初探Apache Kylin【麒麟】
  6. MATLAB数据分析
  7. C/C++ BugPitfalls
  8. python数据可视化编程实战 第2版 github_Python数据可视化编程实战(三):在Mac OS X上安装matplotlib...
  9. 机器学习基础-朴素贝叶斯分类
  10. [转载] 数组快速排序python_python实现快速排序
  11. 爆锤数据结构(期末复习笔记)
  12. 通道和色彩调整——冷色调图片
  13. Thingsboard 时序数据和属性数据
  14. 脑机接口竞赛( BCI competition)数据集,其他数据集下载链接
  15. 为什么现在的视频都会加入自动字幕功能?
  16. 管理系统类项目的登陆与权限功能的实现
  17. qt助手服务器超时,hfs网络文件服务器
  18. 程序员的职业发展规划
  19. hadoop查看文件总条数及按某个关键词查询
  20. 经典算法之直接选择排序

热门文章

  1. Matlab三维数据画图和等高线数据提取
  2. 商业银行清算业务(一)
  3. 从键盘输入一个已确定长度的字符串。然后将这个字符串倒序输出
  4. c语言for循环除法运算,C语言入门这一篇就够了
  5. Python获取全年法定节假日时间
  6. 对诺贝尔奖的一点点个人看法
  7. 计算机专业集齐七龙珠,集齐七颗龙珠 为你召唤一台飞行堡垒8
  8. 45天学会go --第2天go语言基本数据类型
  9. 解决塌陷的几种·办法
  10. 黑马52期学后总结笔记(三)