与Fluffykins准将一起学习Node.js第一部分:同步,异步和创建第一个服务器!

by Mariya Diminsky

通过玛丽亚·迪明斯基(Mariya Diminsky)

与Fluffykins准将一起学习Node.js第一部分:同步,异步和创建第一个服务器! (Learn Node.js with Brigadier Fluffykins Part I: Sync, Async, and Creating Your First Server!)

Welcome to Part I of Learn Node.js With Brigadier Fluffykins, a series created to help you easily understand Node.js ❤

欢迎来到使用Fluffykins准将学习Node.js的第一部分,该系列旨在帮助您轻松理解Node.js❤

A new adventure has arrived! I will be taking you step by step from initial Node.js install to creating your first server, to customizing your responses, understanding streams and events, as well as using frameworks. Let’s begin.

新的冒险到来了! 我将逐步指导您从最初的Node.js安装到创建您的第一个服务器,以自定义响应,理解流和事件以及使用框架。 让我们开始。

Brigadier Fluffykins wants to make sure you’ve reviewed the basics of callbacks and promises. If not:

旅长Fluffykins想让回调承诺确保在审核完基础知识。 如果不:

  • Watch this video & read this article on callbacks.

    观看视频和阅读文章回调

  • Watch this video & read this article on promises.

    观看视频和阅读这个文章的诺言

It’s ok if you don’t understanding everything right away. The important thing is that you are introduced to these concepts now. We want your brain to begin adjusting to the Node.js programming patterns you will implement throughout these lessons. Good luck and happy learning! :)

如果您不立即了解所有内容,也可以。 重要的是,现在向您介绍了这些概念。 我们希望您的大脑开始适应将在这些课程中实现的Node.js编程模式。 祝你好运,学习愉快! :)

Today’s lesson will cover:

今天的课程将涵盖:

  • What Node.js is and what you can build with it.

    什么是Node.js,以及可以使用它进行构建。
  • Brief overview of how the web works(i.e. Client, Server relationship).

    网络工作原理的简要概述(即客户端,服务器关系)。
  • Downloading and installing Node.js on Mac/Windows/Linux.

    在Mac / Windows / Linux上下载并安装Node.js。
  • What asynchronous/synchronous mean, and what non-blocking/blocking mean.

    异步/同步是什么意思,非阻塞/阻塞是什么意思。
  • How to create your first server.

    如何创建您的第一台服务器。

什么是Node.js? (What is Node.js?)

Node.js is an open source cross platform runtime environment that allows you to build scalable network applications on the server-side.

Node.js是一个开源的跨平台运行时环境,可让您在服务器端构建可伸缩的网络应用程序。

By runtime environment, I mean that inside Node.js is the V8 JavaScript runtime — the same one used (and developed by) the Google Chrome browser on the client-side. Using Node.js’s modules and libraries — explained later in this series — we have a way to:

在运行时环境中,我的意思是Node.js内部是V8 JavaScript运行时 -客户端上使用Google Chrome浏览器(并由其开发)的运行时 。 使用Node.js的模块和库(本系列后面将进行解释),我们可以采用以下方法:

  • Scale apps as traffic increases

    随着流量的增加扩展应用程序
  • Build chat rooms and other data-heavy apps

    建立聊天室和其他大量数据的应用程序
  • Directly manipulate database information

    直接操纵数据库信息
  • Access and shape the files in our system based on preference

    根据偏好访问并调整我们系统中的文件
  • Route requests (for website’s html/css/js pages) and monitor traffic

    路由请求(针对网站的html / css / js页面)并监控流量
  • Have faster uploads and the ability to show the progress of those uploads

    上传速度更快,并能够显示这些上传的进度
  • Customize our responses to these requests via routing and redirecting

    通过路由和重定向来自定义我们对这些请求的响应

Due to V8 and Node.js mostly being written in C and C++(even though many modules are written in JavaScript), Node.js is very fast. This is super important when you have an application that needs scaling.

由于V8和Node.js主要是用C和C ++编写的(尽管许多模块是用JavaScript编写的),所以Node.js的速度非常快。 当您有需要扩展的应用程序时,这是非常重要的。

Imagine thousands of users hitting your app, and thus requesting info from your server. What do you think will happen? You have no way of handling these requests, and even if you do, they may be synchronous (explained later). Users end up waiting in line behind thousands of other users for the necessary files to return. Loading speeds are slow, creating a poor user experience and causing you to lose business.

想象成千上万的用户点击您的应用程序,从而从您的服务器请求信息。 您认为会发生什么? 您无法处理这些请求,即使您这样做,它们也可能是同步的(稍后说明)。 用户最终在成千上万的其他用户之后排队等待返回所需的文件。 加载速度很慢,造成不良的用户体验,并导致您失去业务。

Scaling your app when traffic hits is one of the biggest challenges an app faces in the early stages.

在流量达到峰值时扩展应用程序是应用程序在早期阶段面临的最大挑战之一。

Node.js allows you to operate a huge number of connections simultaneously and asynchronously — this basically means it allows for scalability. On top of this, you have libraries to help you customize the handling of these issues.

Node.js允许您同时和异步操作大量连接-这基本上意味着它具有可伸缩性。 最重要的是,您具有库来帮助您自定义这些问题的处理。

客户端和服务器:传统模型 (Client and Server: The Traditional Model)

Before we continue I want to give a brief overview of how the web works via client and server. If you already understand this go ahead and skip this part.

在继续之前,我想简要概述一下网络如何通过客户端和服务器工作。 如果您已经了解了这一点,请跳过此部分。

When I say client, I mean anyone who is requesting information.

当我说客户时,我指的是任何需要信息的人。

When I say server, I mean anyone who is processing a request and responding back with the necessary information.

当我说服务器时,我指的是正在处理请求并以必要信息进行响应的任何人。

For example, when you go to type in:

例如,当您键入:

You are about to initiate several requests for the website’s HTML page, it’s CSS stylesheets, it’s JavaScript documents, and so on. You are asking or requesting their server to show you the page and all the documents associated with it.

您将对网站HTML页面,CSS样式表,JavaScript文档等发起多个请求。 您正在要求要求他们的服务器向您显示该页面以及与之关联的所有文档。

When the website’s servers receives these requests, they respond with the HTML page, the CSS stylesheets, and whatever else you may need to view that page. This is the gist of it.

当网站的服务器收到这些请求时,它们会以HTML页面,CSS样式表以及查看该页面所需的其他内容进行响应。 这是要点。

It’s important to note that anyone can be a client or a server. When you are creating an app locally you are in fact acting as a client and a server (such as localhost:3000). More on that later.

重要的是要注意,任何人都可以是客户端或服务器。 在本地创建应用程序时,实际上是在充当客户端和服务器(例如localhost:3000 )。 以后再说。

For now, let’s explore how Node.js handles these requests compared to the old-school model. We’ll use animations that Brigadier Fluffykins made for us. The orange is Brigadier Fluffykin’s request to his favorite website and the green is the response from the server. Slow and steady:

现在,让我们探索与老式模型相比,Node.js如何处理这些请求。 我们将使用Fluffykins准将为我们制作的动画。 橙色是准将Fluffykin对他最喜欢的网站的请求,绿色是服务器的响应。 缓慢而稳定:

The traditional client-server model involves the client initializing a request first. Each request connection creates a new thread — a new process where code runs — thus taking up memory in your system. This eventually creates scalability issues due to memory running out or your server crashing due to an over flood of requests (high user traffic).

传统的客户端-服务器模型涉及客户端首先初始化请求。 每个请求连接都会创建一个新线程(一个运行代码的新进程),从而占用系统中的内存。 由于内存用完或由于请求过多(用户流量过大)而导致服务器崩溃,最终会导致可伸缩性问题。

If you’re interested in diving deeper in how the client-server model works, I recommend exploring here.

如果您有兴趣深入了解客户端-服务器模型的工作原理,建议在此进行探索。

客户端和服务器:使用Node.js (Client and Server: With Node.js)

With Node.js, both the client and server can initiate two-way connections allowing data to freely communicate between the two. Even though Node.js is single threaded — just like Javascript —and only one process happens at a time (explained later in the series), it ‘acts’ multi-threaded by processing requests via callbacks and promises. It’s thus able to support thousands of concurrent connections in an non-blocking/asynchronous manner.

借助Node.js,客户端和服务器都可以启动双向连接,从而允许数据在两者之间自由通信。 即使Node.js是单线程的(就像Javascript一样),并且一次只发生一个进程(在本系列的后面部分进行解释),但它通过回调promise处理请求来“执行”多线程 因此,它能够以非阻塞/异步方式支持数千个并发连接。

Node.js can act as the client or the server or both. How awesome is that!?

Node.js既可以充当客户端,也可以充当服务器,或者同时充当这两者。 那太棒了!?

As the server, a user visits your website and make requests (for HTML, CSS, and JavaScript files). Node.js receives these requests and sends a response (the HTML, CSS, and JavaScript files requested) and so on.

作为服务器,用户访问您的网站并提出请求(获取HTML,CSS和JavaScript文件)。 Node.js接收这些请求并发送响应(请求HTML,CSS和JavaScript文件)等等。

As a client, Node.js requests content from another site. For example, when a client wants to post something to Pinterest or Twitter from your site.

作为客户端,Node.js从另一个站点请求内容。 例如,当客户想要从您的网站向Pinterest或Twitter发布内容时。

To use Node.js as a client you need to install the Request library (We’ll talk about installing modules and libraries for Node.js later in this series).

要将Node.js用作客户端,您需要安装Request库(本系列后面的内容将讨论为Node.js安装模块和库)。

It’s important to realize that Node.js doesn’t do anything by itself. It’s not a web server. It’s just a runtime environment. If you want a web server, you bet your dilly da hoo ha that you need to write that server yourself young man (woman…child…cat…you get the point). You want to add information to your files? You gotta write that yourself too — Node.js doesn’t magically create this for you, but it sure adds a lot of great functionality you can play with. And Brigadier Bunny Fluffykins is going to teach you how! Yeah!

重要的是要意识到Node.js本身不会做任何事情。 这不是Web服务器。 这只是一个运行时环境。 如果您想要一个Web服务器,那么您打赌,您需要自己写那个服务器(年轻人……女人……孩子……猫……您明白了)。 您要向文件中添加信息吗? 您也必须自己编写代码-Node.js不会为您神奇地创建它,但是它确实增加了许多不错的功能供您使用。 准将Bunny Fluffykins将教你如何! 是的

下载并安装Node.js (Downloading and Installing Node.js)

  1. Open your command line terminal. If you don’t know how to find your command line, here are a few links that may help:

    打开命令行终端。 如果您不知道如何找到命令行,则以下一些链接可能会有所帮助:

2. Next, make sure Git is up and running:

2.接下来,确保Git已启动并正在运行:

  • You can download it here.

    您可以在此处下载。

  • Watch this 4 minute video intro on git.

    观看有关git的 4分钟视频介绍。

  • Read this article if you still need help.

    如果您仍然需要帮助,请阅读此文章

3. Download Node.js onto your system.

3.将Node.js 下载到您的系统上。

To check if you installed it, type in node -v in your command line, you should see the version number pop up:

要检查是否已安装,请在命令行中输入node -v ,您应该会看到弹出的版本号:

Now that you have Node.js installed, you access the node command in your terminal, and type JavaScript code in your shell!

既然已经安装了Node.js,则可以在终端中访问node命令,然后在shell中键入JavaScript代码!

You can also execute code from a JavaScript file:

您还可以从JavaScript文件执行代码:

Let’s create a file called bunny.js in your code editor (such as Sublime, Brackets or Atom). Type in console.log(‘I will give Brigadier Fluffykins 20 carrot bits’) inside the file, or download this zip which includes this file as well as the next few files we need for the rest of the lesson.

让我们在代码编辑器中创建一个名为bunny.js的文件(例如Sublime,Brackets或Atom)。 在文件内键入console.log(“我将给Brigadier Fluffykins 20个胡萝卜位”) ,或下载 zip文件,其中包括此文件以及本课程其余部分需要的其他几个文件。

Press ctrl + c inside the terminal for Mac twice to exit out of the node process (I believe it’s killall node for Windows — correct me if I’m wrong here).

在Mac终端上按Ctrl + C两次,退出节点进程(我相信这是Windows的Killall节点 ,如果我错了,请纠正我)。

Now find where your file is located. In my case, I moved to Desktop, then the folder where I saved the bunny.js file (nodestory). You may have it saved on your Desktop. Now in the shell type node bunny.js and VOILA! Your JavaScript shows up in the terminal! :)

现在找到文件的位置。 就我而言,我移至桌面,然后移至保存bunny.js文件的文件夹( nodetory )。 您可能已将其保存在桌面上。 现在在shell中键入node bunny.js和VOILA! 您JavaScript将显示在终端中! :)

异步和同步代码 (Asynchronous & Synchronous Code)

In order for Node.js to handle thousands of concurrent connections, it needs to handle them asynchronously, in a non-blocking way. What this means is you can have more than one action running at the same time, you saw this in the second animation.

为了让Node.js处理数千个并发连接,它需要以非阻塞方式异步处理它们。 这意味着您可以同时运行多个动作,这是在第二个动画中看到的。

Blocking — or synchronous — on the other hand, will run only one action at time. It will not allow a second action to run until it’s finished. When we sent a request for a file, we had to wait for the server to respond until we could send another request. This takes a really long time for Brigadier Fluffykins, and he was unhappy.

另一方面,阻塞(或同步)一次只能运行一个动作。 在完成之前,它将不允许第二个动作运行。 发送文件请求时,我们必须等待服务器响应,直到可以发送另一个请求。 对于弗拉菲金准将来说,这花费了很长时间,他并不高兴。

If you create code asynchronously, you can run actions in parallel. This can take less than half as much time as using a synchronous approach.

如果异步创建代码,则可以并行运行操作。 与使用同步方法相比,这可能花费不到一半的时间。

Although Node.js was purposefully created to be non-blocking, it allows developers the option to choose how they want their code run via changeable methods in their libraries. For example, Node.js has an appendFile method that can append something new to your file asynchronously or synchronously. Here’s another example:

尽管Node.js的创建是非阻塞的,但它允许开发人员选择通过其库中的可变方法选择其代码运行方式的选项。 例如,Node.js有一个appendFile方法,可以异步同步地将新内容添加到文件中。 这是另一个例子:

Follow steps 1–5, or download this zip with files I’ve already created for you:

请按照步骤1-5进行操作,或者下载包含我已经为您创建的文件的该zip文件:

  1. First let’s create a folder called ‘nodestory’ .

    首先,我们创建一个名为“ nodestory ”的文件夹。

  2. Create these 3 files: wishlist.html, bunnySync.js and bunnyAsync.js inside the folder.

    在文件夹中创建以下3个文件: wishlist.htmlbunnySync.jsbunnyAsync.js

  3. Open this folder in your code editor(Sublime, Brackets, Atom etc).

    在代码编辑器中打开此文件夹(Sublime,Brackets,Atom等)。
  4. In wishlist.html copy and paste this in:

    wishlist.html中,将其复制并粘贴到以下位置:

5. In bunnySync.js copy and paste this in:

5.在bunnySync.js中,将其复制并粘贴到:

Ok now run node bunnySync.js in your terminal:

好的,现在在终端中运行node bunnySync.js

Notice how our alert is printed in the same order as when we wrote the code? Now let’s try the same concept but asynchronously/non-blocking.

注意到我们的警报是如何以与编写代码时相同的顺序打印的? 现在让我们尝试相同的概念,但异步/非阻塞。

In bunnyAsync.js paste this in — make sure it’s the right file name:

bunnyAsync.js中粘贴此文件-确保它是正确的文件名:

Ok now run node bunnyAsync.js in your terminal:

好的,现在在终端中运行节点bunnyAsync.js

Notice how our alerts, no matter the order, all print before the file is fully read? Reading the file takes longer then using the console.log function, and thus our alerts are printed first. Once the file is read, it eventually prints.

请注意,无论顺序如何,我们的警报如何在完全读取文件之前全部打印出来? 与使用console.log函数相比,读取文件花费的时间更长,因此,我们的警报将首先打印出来。 读取文件后,它将最终打印。

创建您的第一台服务器 (Create Your First Server)

It’s thaaaaaaat special time of year… to create your first server!

现在是一年中的特殊时间……创建您的第一台服务器!

Woohoo! I am so excited for you! We’ll be going through several examples, so either create a file called server.js and paste this in:

hoo! 我为你感到兴奋! 我们将通过几个示例,因此创建一个名为server.js的文件并将其粘贴到:

…or open the server.js file in the zipped folder I provided earlier.

…或在我之前提供的压缩文件夹中打开server.js文件。

Make sure that only the http and fs variables — as well as ‘STEP #1’ — are uncommented. Review the code and deliberate on what you think is happening before you continue reading.

确保仅注释httpfs变量以及“ STEP#1”。 在继续阅读之前,请仔细阅读代码并仔细考虑所发生的事情。

As you may have noticed, along with modules and third-party libraries, Node.js also comes wth an extensive list of methods. You most likely won’t be using all of them — it really depends on what you’re building.

您可能已经注意到,Node.js与模块和第三方库一起还包含大量方法。 您很可能不会全部使用它们-实际上取决于您要构建的内容。

Now type node server.js in your terminal to start the server.

现在,在终端中键入node server.js以启动服务器。

Go to your url header and type localhost:3000 to see the response you just sent:

转到您的url标头,然后键入localhost:3000以查看刚刚发送的响应:

Ok, what’s happening here?

好的,这是怎么回事?

For every request, you need a response. First, we respond to the client by setting the status code in the header to 200, meaning this website is OK, ready to go!

对于每个请求,您都需要一个答复。 首先,我们通过将标头中的状态代码设置为200来响应客户,这意味着该网站可以正常运行!

You can check the headers by clicking option + command + J in Chrome on a Mac, or right clicking and choosing inspect then clicking the Network tab (it’s one of the options next to the Console tab). If you don’t see anything under Network just hit refresh. Otherwise click the page and you will see under Headers the status code and what kind of requests the client made (in our case, “localhost:3000”). This is a GET request, since we want to get a file from a server.

您可以通过以下方式检查标题:在Mac上的Chrome中单击选项+命令+ J ,或右键单击并选择检查,然后单击“ 网络”标签(这是“ 控制台”标签旁边的选项之一)。 如果您在“ 网络”下看不到任何内容,请点击刷新。 否则,请单击页面,您将在标题下看到状态代码和客户端发出的请求类型(在我们的示例中为“ localhost:3000”)。 这是一个GET请求,因为我们要从服务器获取文件。

Here’s what would happen if we set our headers to 404:

如果将标头设置为404,将会发生以下情况:

Try it out in your code and see if you can get a 404 status code.

在您的代码中尝试一下,看看是否可以获得404状态代码。

Headers and status codes are an interesting topic by themselves, but I won’t go into that now. I have included resources in the end, if you’d like to research this more.

标头和状态代码本身就是一个有趣的话题,但是我现在不再赘述。 最后,如果您想进一步研究的话,我会提供资源。

Next we have the response we want to send back to the client, or what the client will actually view on their page using the write method. Then we close the connection with the end method.

接下来,我们将收到要发送回客户端的响应,或者客户端将使用write方法实际在其页面上查看的内容。 然后我们使用end方法关闭连接。

Lastly, we set up the port that our server will listen for requests. This can be 3000, 8080, or basically whatever you want. Just make sure you go to localhost:8080 if, for example, you’re using port 8080.

最后,我们设置服务器侦听请求的端口。 可以是3000、8080,或者基本上是您想要的任何值。 例如,如果您使用的是端口8080,请确保进入localhost: 8080。

It’s a good practice to set the headers first before you set the response, especially because headers come before the body in the HTTP responses.

最好在设置响应之前先设置标头,尤其是因为标头位于HTTP响应的正文之前。

You just learned to create your first server! Pat yourself in the back, or slap yourself in the face — whatever works for you!

您刚刚学会了创建第一个服务器! 拍拍自己的后背,或者拍打自己的脸-一切适合您!

Let’s continue our adventure by building one of the more common forms you’ll see for HTTP servers. This is the same as what we just created, except there are some slight syntax differences which focus on events and event emitters (explained later in the series).

让我们继续构建您将在HTTP服务器上看到的最常见的表单之一,以继续我们的冒险之旅。 这与我们刚创建的相同,除了语法上有一些细微的差异,这些差异集中在事件事件发射器上 (在本系列的后面部分进行解释)。

Comment out ‘STEP #1’ and uncomment ‘STEP #1.5’.

注释掉“ STEP#1”,并取消注释“ STEP#1.5”。

This is really important: before you do anything else, be aware that when you start a server then change something again in the file, the changes won’t be visible until you stop the server and start it again. There are libraries that will automatically restart the server for you upon detecting changes (like Nodemon), but don’t worry about setting that up right now.

这真的很重要:在执行其他任何操作之前,请注意,当启动服务器然后再次更改文件中的更改时,更改将不可见,直到您停止服务器并再次启动它为止。 有一些库可以在检测到更改时自动为您重启服务器(例如Nodemon ),但是不必担心现在就进行设置。

For now, to stop the server manually go into your terminal and press control + C for Mac (again, I believe it’s killall node for Windows) then either press the up arrow to go through the previous commands you typed, or manually type in node server.js.

现在,要手动停止服务器,请进入终端并在Mac上按Control + C (同样,我相信这是Windows的killall节点 ),然后按向上箭头以浏览您输入的先前命令,或者手动输入node server.js

You should see this:

您应该看到以下内容:

Notice that we can send some basic HTML inside the end method, thus sending a response and ending our connection at the same time. We can also store our server in a variable to make it more readable when we are using events such as request. It’s important to note that the request event is not the same as the Request third-party library. This confused me when I first learned Node.js, and I wouldn’t want you to go through the same thing. We’ll be talking about these in the next few lessons of the series.

注意,我们可以在end方法内发送一些基本HTML,从而发送响应并同时终止我们的连接。 我们还可以将服务器存储在变量中,以在使用诸如request之类的事件时提高其可读性。 请务必注意, 请求事件与请求第三方库不同。 当我第一次学习Node.js时,这让我感到困惑,并且我不想让您经历同样的事情。 我们将在本系列的下几节课中讨论这些内容。

额外资源 (Extra Resources)

I implore you to go out and do some research. Make the most out of the time that you have. Here are a few places you can start:

我恳请你出去做一些研究。 充分利用您的时间。 您可以从以下几个地方开始:

Congrats! You’ve made it through Learn Node.js With Brigadier Fluffykins Part I! Now you’ll be able to explain the basics of Node.js as well as what you can build with it. You gained an intro on how async/non-blocking and sync/blocking code works, and the benefits that Node.js provides with async programming. Best of all, you were finally able to set up your very first server!

恭喜! 您已通过使用Fluffykins准将学习Node.js做到了第一部分! 现在,您将能够解释Node.js的基础知识以及可以使用它进行构建的内容。 您了解了异步/非阻塞和同步/阻塞代码的工作方式,以及Node.js通过异步编程提供的好处。 最重要的是,您终于能够设置您的第一台服务器!

Wow. Seriously, great job. Brigadier Fluffykins commends your effort.

哇。 说真的,干得好。 Fluffykins准将赞扬您的努力。

We will go deeper into these topics as well as others we’ve only scratched in the next few lessons. Thank you for reading and stay tuned.

在接下来的几节课中,我们将深入探讨这些主题以及我们仅涉及的其他主题。 感谢您的阅读和关注。

Keep your wisdom up to date by clicking the ❤ below and following, as more Learn Node.js With Brigadier Fluffykins is coming soon to Medium!

单击下面的❤,保持您的最新知识,更多信息了解Fluffykins与Brigadier Fluffykins即将发布!

Part I: Sync, Async, and Creating Your First Server!

第一部分:同步,异步和创建您的第一台服务器!

Part II: Events, EventEmitter & Event Loop

第二部分:事件,EventEmitter和事件循环

Part III: Request Object, Configure Routes, Serve Files

第三部分:请求对象,配置路由,服务文件

翻译自: https://www.freecodecamp.org/news/learn-node-js-with-brigadier-fluffykins-i-basics-async-sync-create-your-first-server-b9e54a45e108/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值