使用.net core在Ubuntu构建一个TCP服务器
介绍和背景
TCP编程是网络编程领域最有趣的部分之一。在Ubuntu环境中,我喜欢使用.NET Core进行TCP编程,并使用本机Ubuntu脚本与TCP服务器进行通信。以前,我在.NET框架本身写了一篇关于TCP服务器和客户端的文章。现在,.NET框架本身将是开源的。我想写一些关于他们之间的沟通渠道。基本上,我只是测试在新的.NET环境下工作的情况,而不是在旧的.NET框架环境中工作。
然而,在这篇文章中,我有一大堆的额外功能可供你使用。我将向您展示您将使用的方法来构建自己的TCP服务器,使用.NET核心程序集以及如何通过网络与他们进行通信。对于客户端应用程序,我不会构建任何东西。相反,我将使用允许通过TCP和UDP协议进行通信的本地脚本。
议程是这样的:
-
构建和托管一个内置.NET Core的TCP服务器
-
启动请求并使用TCP客户端本机脚本将文本数据和文件数据发送到服务器。
这些是我会在这篇文章中引导你的一些东西,我也会澄清一切的目的。
我们不打算在这里建立任何特殊的应用程序,但是TCP是传输层中使用最广泛的协议(与UDP相反),我们经常使用的大多数应用程序和服务都依赖于这个协议。HTTP,FTP,SMTP和所有其他类似协议直接依赖于TCP,并使用基于TCP协议的套接字(端口)进行通信。因此,您可以从最小的程序中启动您的服务器,并在其上构建一个庞大的企业应用程序。它可以根据应用编程框架和连接到它的客户端(或用户)的需要进行扩展。
但是,我不打算谈论如何构建这些复杂的应用程序,但是我将简要介绍一下TCP服务器和基于客户端的通信。为什么写这个帖子?我将介绍跨平台环境下的TCP消耗。我将使用.NET Core创建服务器。其余部分将在本地完成,我将在Ubuntu中使用“nc”命令与我刚刚创建的服务器进行通信。因此,这个想法是让你了解如何在.NET Core中构建一个服务器来提高效率和控制能力,以及如何使用多个平台及其服务与服务器进行通信,从而使用户能够与TCP服务器通信。那么,让我们开始吧。
构建服务器端
在.NET环境中,System.Net命名空间包含了可用于学习和编程目的的所有参考资料。在服务器端编程任务中,我将使用TcpListener对象来处理传入的TCP通信。基本上,这是一个本地的TCP部分,你会很快习惯它。我一直在使用这个对象以及在其生命周期中使用这个对象的程序,用于我自己的个人应用程序和一些基于网络的应用程序,客户端应用程序,设备和机器能够通过路由器(调制解调器,或WLAN热点等)。这样,我可以创建一个使用TCP协议进行通信的中央服务器,并且可以使用TCP进行通信的客户端也可以从此服务器发送或接收数据。然而,我不会深入到以多种格式通过网络提交和传输数据。为了简单起见,我将把事情简单明了,因此我将不得不以纯文本格式工作。
服务器 - 客户端通信如何在TCP环境中工作的基本演示在以下创建的位图图形艺术中得到了演示:
图1:服务器 - 客户端设置
如图所示,服务器控制资源的使用和使用方式。客户端可以使用任何可以通过网络使用TCP协议进行通信的设备。服务器处理请求并授予对资源的访问权限。就像与其他程序交互一样,TCP客户端可以与TCP服务器交互,发送命令,发送请求,发送选项选择(例如选择要触发的服务)等等。然后,TCP服务器处理这些请求,并根据这些请求以及正在传递的数据的值生成响应。TCP服务器可以:
-
通过TCP协议处理传入的请求。
-
作为服务在后台运行; 哪些其他服务器也可以做。
-
将线路上的数据资源作为字节流发送。
-
尽管TCP服务器被认为是共享消息的纯文本框架,但实际上不是消息,而是发送的字节。
-
TCP通信中的序列实际上是发送的字节,而不是消息。所以,客户端应该能够处理传入的字节。
-
提供可靠的,有序的和错误检查的方法和机制,在网络上进行通信,而不是我们正在创建的服务器,而是协议。
在.NET Core中,TCP侦听器允许您通过使用固定大小的静态缓冲区来处理可用的字节数。有时,可能不会发送数据来填充缓冲区,有时缓冲区可能不足以覆盖所有的缓冲区。
运行服务器的源代码就像下面这样简单:
-
实例化对象。
-
设置IP地址来监听和端口监听。
-
等待客户连接。
这一步承载服务器。在这个阶段,承载服务器的程序应该保持活动并运行,否则程序将终止,关闭服务器本身。看看下面给出的代码:
-
IPAddress address = IPAddress.Parse(“127.0.0.1” );
-
listener = new TcpListener(address,port);
-
listener.Start();
-
//代码停止服务器并使用
-
// listener.AcceptTcpClientAsync();
-
//获取连接客户端的函数
这段代码完成了我们在服务器端需要做的工作。即主持它。我用下面的代码实际上表示服务器正在运行,并在此刻处于活动状态。服务器本身不显示为正在运行。
-
Console.WriteLine($ “Server started。Listen to TCP clients at 127.0.0.1:{port}” );
在这个阶段之后,我们需要停止服务器自行终止。而不是保持相同的功能,并在这行代码后,我创建了一个分离的功能,并在那里添加代码等待客户端。我们班有两个功能,
-
启动服务器
-
听客户
这是执行程序中大部分工作的第二个功能。这里是我们可以添加异步模式和多线程来支持多个客户端同时连接的地方。不过,我并不打算在这一节中进一步深入。所以,正确的代码来实际启动服务器,并听取客户端如下所示:
-
using System;
-
using System.Net;
-
using System.Text;
-
using System.Net.Sockets;
-
namespace ConsoleApplication
-
{
-
class TcpHelper
-
{
-
privatestatic TcpListener listener { get; set; }
-
privatestaticbool accept { get; set; } = false;
-
publicstaticvoid StartServer(int port) {
-
IPAddress address = IPAddress.Parse("127.0.0.1");
-
listener = new TcpListener(address, port);
-
listener.Start();
-
accept = true;
-
Console.WriteLine($"Server started. Listening to TCP clients at 127.0.0.1:{port}");
-
}
-
publicstaticvoid Listen()
-
{
-
if(listener != null && accept)
-
{
-
// Continue listening.
-
while (true)
-
{
-
Console.WriteLine("Waiting for client...");
-
var clientTask = listener.AcceptTcpClientAsync(); // Get the client
-
if(clientTask.Result != null)
-
{
-
Console.WriteLine("Client connected. Waiting for data.");
-
var client = clientTask.Result;
-
string message = "";
-
while (message != null && !message.StartsWith("quit"))
-
{
-
byte[] data = Encoding.ASCII.GetBytes("Send next data: [enter 'quit' to terminate] ");
-
client.GetStream().Write(data, 0, data.Length);
-
byte[] buffer = newbyte[1024];
-
client.GetStream().Read(buffer, 0, buffer.Length);
-
message = Encoding.ASCII.GetString(buffer);
-
Console.WriteLine(message);
-
}
-
Console.WriteLine("Closing connection.");
-
client.GetStream().Dispose();
-
}
-
}
-
}
-
}
-
}
-
}
此代码启动服务器并继续等待新的客户端。一旦客户端连接,它会向客户端请求数据,并将该数据发布到客户端发送“退出”到服务器。基本上,这是一个非常简单但功能强大的服务器示例,用于教育目的。当然,我们现在也需要从主函数中调用这些函数,以便运行该项目。
-
public static void Main(string [] args)
-
{
-
//启动服务器
-
TcpHelper.StartServer(5678);
-
TcpHelper.Listen(); //开始聆听
-
}
目前我们已经完成了服务器端的脚本。服务器设置好后,会听取客户端的请求和数据,它们会传递到我们的服务器上。我们现在需要运行程序并启动服务器来监听请求。我不深入.NET核心执行过程和构建过程的深入; 至于那个,看我的另一个帖子:
-
在Linux上使用.NET Core快速启动
运行程序,只需要执行下面的命令,
运行dotnet
输出结果
如图2所示:服务器启动
正如你所看到的,TCP服务器在IP上启动,我们指定了我们在函数调用中传递的端口。
其余的留给客户端
正如我之前谈到的,我将使用本地TCP客户端而不是.NET核心的TCPClient对象,这样即使在系统上没有安装.NET的情况下也可以使用服务器(例如,使用.NET框架的TCPClient对象)。在这篇文章中,我将在Unix(Linux和衍生)系统中使用“netcat”命令脚本。沟通可以简单地完成。您可以从在线资源中了解更多关于这个脚本的内容,因为我不想再深究。我只是想演示这个用法。要了解更多信息,您可以访问以下任一网址并了解更多信息:
-
nc - Unix,Linux命令
-
如何使用Netcat在VPS上建立和测试TCP和UDP连接
-
nc(1) - Linux手册页
您将能够理解如何使用此命令来充当客户端。这也允许你创建一个充当服务器的程序脚本,监听网络上的请求,但我们对这些因素不感兴趣。相反,我们只是期待发送一个请求到服务器,并传递一些将显示在屏幕上的数据。
连接和发送数据到服务器:
第一步是连接到TCP服务器。我们需要两件事来建立连接,
-
IP地址
-
端口连接
我们将把它们作为参数传递给
$ nc 127.0.0.1 5678
下面的屏幕出现(我们的服务器接受请求并返回一条消息)
图3:客户端连接
(查看我们服务器的代码,了解更多信息。 )
接下来,我们可以从这个终端发送数据,因为它需要更多的数据。我们将发送几个字节的数据,然后发送“退出”来终止连接。让我们看看这是如何工作的上下文。
图4:客户端将数据发送到服务器
我们发送了三条消息到服务器。所有这些都被检查,最后在最后一条消息,流被关闭,终端开始要求更多的命令(而不是要求更多的数据)。为什么?如果你注意,你会看到“quit”命令已经被设置为连接的终结符。当我们发送这个命令时,连接终止,我们需要再次启动连接。现在,我们来看另一边。
图5:服务器端消息日志
看看每个事件的行为如何变化。一旦我们的客户端连接,在这里记录一条消息:“客户端连接。等待数据“。当客户端连接时显示此消息。您还可以记录该客户的时间和其他详细信息。我们通过数据传递,在“退出”之后,你可以看到有一个“关闭连接”的日志,在另一端也应该显示,但不幸的是,我错过了这一点。您必须已经知道使用客户端连接到服务器并发送数据。
兴趣点
最后,这篇文章简要介绍了.NET Core中的TCP编程,以及如何通过使用其他平台服务与服务器进行通信来抽象出整个概念。
更多精彩文章请关注我们的微信公众号FocusDotCore: