在 C# 中设置客户端-服务器通信
这个简单的编程教程将讨论客户端-服务器环境中的数据传输。它还将通过 TCP 套接字编程为客户端-服务器通信模型提供基于 C# 的实现。
传输控制协议 (TCP)
开放系统互连 (OSI) 是一种广泛采用的通信参考模型,它解释了计算机如何相互通信。它确保无差错的数据从一端传送到另一端。
分层 OSI 模型定义了发送或接收数据时要遵循的一些规则和协议。所有层都单独工作,并执行从一端到另一端传输数据的任务。
本文将仅解释传输层。该层使用的主要协议是传输控制协议(TCP),主要职责如下:
- 在两端建立连接,然后在通信结束时销毁该连接。
-
数据传输包括以下任务:
- 确保数据可靠性并检查数据是否按顺序传输且无错误。
- 检测错误(如果有)并重新发送丢失的数据包。
- 控制数据包的流量和速率。
- 确认并设置标志。
在 C#
中设置客户端-服务器通信
让我们转向使用 C# 语言在 .NET 框架中实现客户端/服务器应用程序。我们将使用 Visual Studio Enterprise Edition 2019 进行此实施。
我们将创建两个应用程序,一个用于客户端,一个用于服务器端。对于测试,这两个应用程序都将驻留在同一台计算机上。
首先,我们将创建一个客户端应用程序。为此,打开 Visual Studio 并创建一个新项目。
然后,选择项目类型 Console Application
并单击 Next
。
将项目名称设为 Client Application
,将解决方案名称设为 ClientServerApplication
。这将为客户端创建一个新项目。
对于服务器端编程,在同一解决方案中创建另一个项目:
这个项目将被命名为 ServerApplication
并且在同一个解决方案中。
创建项目后,你必须添加 Network Comms Dot Net 包文件。为此,你需要使用 NuGet 控制台安装它们。
在图像中像这样转到工具> NuGet 包管理器>包管理器控制台
:
你将在窗口中看到包管理器控制台,如上图所示。在这个控制台中,我们将编写命令:
PM > Install - Package NetworkCommsDotNet - Version 3.0.3
在两个项目中成功安装包后,就可以开始编码了。打开 ServerApplication
项目并编写代码:
public static void ConnectServer() {
IPHostEntry myhost = Dns.GetHostEntry("localhost");
IPAddress ipAddr = myhost.AddressList[0];
IPEndPoint myEndPoint = new IPEndPoint(ipAddr, 11000);
try {
Socket listenerSocket = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listenerSocket.Bind(myEndPoint);
listenerSocket.Listen(5);
Console.WriteLine("Waiting for Client Socket to Coonect...");
Socket socketHandler = listenerSocket.Accept();
// data from the client.
string myData = null;
byte[] dataBytes = null;
while (true) {
dataBytes = new byte[1023];
int bytesRece = socketHandler.Receive(dataBytes);
myData += Encoding.ASCII.GetString(dataBytes, 0, bytesRece);
if (myData.IndexOf("<EOF>") > -1) {
myData = myData.Remove(myData.Length - 5);
break;
}
}
Console.WriteLine("Data Received from Client : {0}", myData);
byte[] msg = Encoding.ASCII.GetBytes("This is the test msg from server");
socketHandler.Send(msg);
socketHandler.Shutdown(SocketShutdown.Both);
socketHandler.Close();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
Console.WriteLine("\n Press any key to continue...");
Console.ReadKey();
}
然后在客户端,编写以下代码:
public static void ConnectClient() {
byte[] myBytes = new byte[1024];
try {
IPHostEntry myhost = Dns.GetHostEntry("localhost");
IPAddress ipAddr = myhost.AddressList[0];
IPEndPoint clientEP = new IPEndPoint(ipAddr, 11000);
Socket senderSocket = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try {
// Connect to the EndPoint
senderSocket.Connect(clientEP);
Console.WriteLine("Client Connect to Server at {0}", senderSocket.RemoteEndPoint.ToString());
// Convert the string into a byte-type array.
Console.WriteLine("Sending a test message");
byte[] msg = Encoding.ASCII.GetBytes("This is a test message from Client<EOF>");
// Send the data using the socket.
int dataSent = senderSocket.Send(msg);
// Receive the reply from the server device.
int dataRec = senderSocket.Receive(myBytes);
Console.WriteLine("Data Received from Server = {0}",
Encoding.ASCII.GetString(myBytes, 0, dataRec));
// delete the socket
senderSocket.Shutdown(SocketShutdown.Both);
senderSocket.Close();
Console.ReadKey();
} catch (ArgumentNullException ane) {
Console.WriteLine(ane.ToString());
} catch (SocketException se) {
Console.WriteLine(se.ToString());
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
在对应项目的 main 函数中调用这些函数后,需要构建项目,也可以构建整个解决方案。然后,为了运行输出,导航到这些项目的文件资源管理器并运行两者的 exe
文件。
相关文章
在 C# 中的接口中实现属性
发布时间:2024/02/01 浏览次数:100 分类:编程语言
-
本文介绍如何在 C# 中的接口中实现属性。C# 中的接口可以有许多不同的属性,以及指定我们应该如何在其中声明属性可用性的访问修饰符。该接口通常充当不同成员和对象的默认实现。
在 C# 中注释文本块
发布时间:2024/02/01 浏览次数:192 分类:编程语言
-
本教程教你如何在 C# 中注释一段文本或代码。作为注解的注释处于更高的抽象级别,编译器在编译 C# 代码时会忽略它。
在 C# 中从子类的构造函数调用基类的构造函数
发布时间:2024/02/01 浏览次数:190 分类:编程语言
-
base 关键字可用于从 C# 中的子类的构造函数调用基类的构造函数。本教程将讨论从 C# 中的子类的构造函数调用基类的构造函数的方法。
C# 中的结构体和类之间的区别
发布时间:2024/02/01 浏览次数:175 分类:编程语言
-
结构体是驻留在堆栈中的值类型变量,而类是驻留在堆中的引用类型变量。在本教程中,我们将讨论 C# 中的结构体和类之间的区别和相似之处。
在 C# 中复制一个对象
发布时间:2024/02/01 浏览次数:120 分类:编程语言
-
有两种主要方法可用于在 C# 中创建对象的单独副本,MemberWiseClone()函数和参数化构造函数方法。在 C# 中使用 MemberWiseClone() 方法复制对象
C# 中的 Java final 等效关键字
发布时间:2024/02/01 浏览次数:59 分类:编程语言
-
C# 中有两个不同的关键字,它们等效于 Java 中的 final 关键字,用于类和函数的 sealed 关键字以及用于字段的 readonly 关键字。本教程将讨论与 Java 中的 final 关键字等效的 C# 关键字。Java final 关键