简介:C#通过System.Net.Sockets命名空间下的Socket类提供了强大的网络编程接口,支持TCP和UDP协议进行网络通信。本文将介绍网络通信基础、TCP和UDP协议的特点,并通过C#源代码实例,阐述如何实现客户端和服务器端的TCP和UDP通信。同时,将涉及异常处理、多线程、性能优化、网络套接字选项设置以及安全性策略,帮助开发者在C#中构建高效和稳定的应用程序。
1. C#网络通信基础
在现代软件开发中,网络通信已成为应用程序不可或缺的一部分。无论是服务端与客户端之间的数据交换,还是分布在不同地理位置系统之间的数据同步,网络通信都在其中扮演着至关重要的角色。C#作为一种功能强大的编程语言,借助.NET框架提供了丰富的网络通信功能。本章将重点介绍网络通信的基础知识,并为读者展示如何使用C#语言在.NET环境中实现基本的网络通信功能。
网络通信不仅仅局限于数据的发送和接收,它还涉及到数据格式的标准化、数据传输的可靠性、协议的选择、通信的效率、安全性以及错误处理等多个方面。因此,本章内容旨在为读者提供一个全面的视角,帮助理解网络通信的核心概念,并掌握C#在.NET框架下进行网络通信的基础实现方法。让我们从网络通信的基础开始探索,逐步深入到协议的细节,并最终过渡到C#的具体实现。
2. TCP通信原理与C#实现
2.1 TCP协议的理论基础
2.1.1 TCP协议的特点
传输控制协议(TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议。在了解如何使用C#实现TCP通信之前,我们首先需要掌握TCP协议的核心特点,以便更好地理解其在实际应用中的表现。
-
面向连接的协议 :TCP在数据传输之前需要建立一个连接,这个连接在数据传输完成后会关闭。这个连接过程涉及到一系列的交互,保证了通信双方都准备就绪。
-
可靠的传输 :TCP保证了数据的可靠传输。即使网络状况不佳,它也会通过重传机制确保数据完整无误地送达目的地。
-
流量控制 :TCP具备流量控制功能,通过滑动窗口协议自动调整传输速率,避免发送方发送速度过快导致接收方来不及处理。
-
拥塞控制 :TCP还实现了拥塞控制算法,防止过多的数据注入到网络中引起网络拥塞。
-
全双工通信 :TCP支持全双工模式,允许数据在两个方向上独立传输,没有固定的方向性。
-
字节流传输 :TCP发送的数据是字节流,不保留记录边界,需要应用层协议来确定数据的分界线。
2.1.2 TCP三次握手与四次挥手
TCP连接的建立和终止是通过一系列的信号交换来完成的,通常被称为“三次握手”和“四次挥手”。
-
三次握手 :
1. 客户端发送一个带有SYN(同步序列编号)标志的数据包到服务端请求建立连接。
2. 服务端接收后,发送带有SYN-ACK标志的数据包作为应答,并将同步序列编号加一。
3. 客户端接收到应答后,发送一个带有ACK标志的数据包,序列号也加一,此时连接建立。 -
四次挥手 :
1. 当数据传输完毕,客户端或服务端中的任何一方想要结束连接,会发送一个带有FIN标志的数据包。
2. 接收方回复一个带有ACK标志的数据包,表示已经收到断开连接的请求。
3. 如果接收方也准备关闭连接,那么它还会发送一个FIN标志的数据包。
4. 最后,发送方回复一个ACK数据包,确认接收到了断开连接的请求,此时连接完全关闭。
掌握这些基础概念对于理解TCP在C#中的实现至关重要,因为它们定义了TCP通信的规则和边界条件。
2.2 C#中TCP通信的实现
2.2.1 创建TCP监听服务
在C#中创建一个TCP监听服务涉及几个关键的.NET类,其中包括 TcpListener 。 TcpListener 类提供了一个简单的API用于监听特定端口上的传入TCP连接请求。
下面是创建一个TCP监听服务的步骤及代码示例:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class TcpServer
{
public static void Main()
{
// 监听IP地址和端口
IPAddress ipGlobal = IPAddress.Parse("127.0.0.1");
int port = 13000;
// 创建一个TcpListener实例
TcpListener tcpListener = new TcpListener(ipGlobal, port);
// 开始监听连接请求
tcpListener.Start();
Console.WriteLine("Waiting for a connection...");
// 主线程继续执行其他任务,直到有连接请求到来
while (true)
{
// 等待客户端连接
TcpClient client = tcpListener.AcceptTcpClient();
// 当有客户端连接时,启动一个新线程来处理连接
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
public static void HandleClientComm(object obj)
{
TcpClient client = (TcpClient)obj;
Console.WriteLine("Connected!");
// 客户端处理逻辑
// ...
// 关闭连接
client.Close();
}
}
在这段代码中, TcpListener.Start() 方法启动了监听器。主线程在 while(true) 循环中等待连接请求,当有新的客户端连接时,主线程创建一个新的线程来处理这个连接。
-
TcpListener:负责监听传入的TCP连接请求。 -
TcpClient:一个已经建立的TCP连接的表示。 -
Thread:代表一个新的线程,用于处理连接。
2.2.2 TCP客户端的构建与连接
构建一个TCP客户端和监听服务类似,但重点是连接到一个正在监听的服务器。在C#中, TcpClient 类同样用于创建客户端实例,它提供了连接服务器的接口。
下面展示了如何使用 TcpClient 类创建一个TCP客户端,并连接到服务器的示例代码:
using System;
using System.Net.Sockets;
using System.Text;
public class TcpClientExample
{
public static void Main()
{
try
{
// 创建TcpClient实例并指定服务器的IP地址和端口号
TcpClient tcpClient = new TcpClient("127.0.0.1", 13000);
// 获取一个NetworkStream,用于发送和接收数据
NetworkStream stream = tcpClient.GetStream();
// 发送数据
string messageToSend = "Hello, Server!";
byte[] data = Encoding.UTF8.GetBytes(messageToSend);
stream.Write(data, 0, data.Length);
// 接收数据
data = new byte[256];
int bytes = stream.Read(data, 0, data.Length);
string responseData = Encoding.UTF8.GetString(data, 0, bytes);
Console.WriteLine("Received: " + responseData);
// 关闭连接
stream.Close();
tcpClient.Close();
}
catch (SocketException e)
{
Console.WriteLine("SocketException: " + e);
}
}
}
在这个示例中, TcpClient 的构造函数用于创建一个新的TCP客户端实例并尝试连接到指定的服务器地址和端口。一旦连接成功,客户端就可以发送数据到服务端,并能够读取从服务端返回的响应。
-
GetStream:方法用于获取连接的NetworkStream对象,该对象用于发送和接收数据。 - 发送数据 :通过
NetworkStream.Write方法发送数据到服务端。 - 接收数据 :通过
NetworkStream.Read方法从服务端接收数据。
客户端与服务端之间的通信基于TCP协议的可靠性,保证了数据的有序性和正确性。这是构建稳定网络应用的基石。
3. UDP通信原理与C#实现
3.1 UDP协议的理论基础
3.1.1 UDP协议的特点
用户数据报协议(UDP)是一种无连接的网络通信协议,它的主要特点在于提供了一种面向非连接的、不可靠的、数据报文服务。UDP工作在传输层,其主要优势在于简单、高效和低开销,这使得它适合于那些对延迟敏感或不要求严格可靠性但要求高吞吐量的应用,如流媒体、在线游戏、VoIP等。
UDP提供了一种最小开销的传输方式,它不包含TCP中复杂的连接管理、流量控制和拥塞控制机制。因此,在传输过程中不需要进行三次握手建立连接,数据包的发送和接收也无需确认。这种简洁性减少了处理数据包的延迟,但也因此牺牲了可靠性。
3.1.2 UDP与TCP的对比分析
UDP和TCP是传输层协议,两者的主要区别在于可靠性、顺序保证、流量控制和拥塞控制。
TCP是一种面向连接的协议,提供了可靠的数据传输服务,保证数据包按顺序到达,并且具备流量控制和拥塞控制机制。而UDP由于其无连接的特性,不保证数据包的可靠性、顺序和完整性。这意味着如果应用层不需要这些特性,使用UDP可以减少通信的开销和延迟。
代码块示例:UDP通信示例
以下是一个简单的UDP通信示例,包括数据包的发送和接收。
// UDP发送端代码
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.100"), 11000);
string message = "Hello UDP";
byte[] buffer = Encoding.ASCII.GetBytes(message);
UdpClient sendClient = new UdpClient();
sendClient.Connect(remoteEndPoint);
sendClient.Send(buffer, buffer.Length);
sendClient.Close();
// UDP接收端代码
UdpClient receiveClient = new UdpClient(11000);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 11000);
byte[] receiveBytes = receiveClient.Receive(ref groupEP);
string receiveString = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine("Received: " + receiveString);
receiveClient.Close();
3.2 C#中UDP通信的实现
3.2.1 UDP数据包的发送与接收
UDP通信的实现涉及数据包的发送和接收。在C#中,可以通过 UdpClient 类来完成这些操作。这个类隐藏了底层的套接字操作,使得UDP数据包的发送和接收变得简单。
发送数据包时,首先创建一个 UdpClient 实例,并指定远程主机的IP地址和端口。然后,使用 Send 方法发送数据。接收数据包时,创建一个 UdpClient 实例,并监听特定端口。使用 Receive 方法接收数据。
3.2.2 UDP客户端与服务端的交互
UDP通信中的客户端和服务端概念不如TCP那么明显,因为UDP不建立连接。但通常,服务端会持续运行并监听特定端口,而客户端则会发送消息到服务端,并可能接收来自服务端的响应。
服务端代码示例:
// 创建UDP客户端监听指定端口
UdpClient server = new UdpClient(11000);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 11000);
// 接收数据
byte[] receiveBytes = server.Receive(ref groupEP);
string receiveString = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine("Received: " + receiveString);
// 可以在此处添加处理消息的逻辑
server.Close();
客户端代码示例:
// 目标服务器地址和端口
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.100"), 11000);
string message = "Hello UDP Server";
byte[] buffer = Encoding.ASCII.GetBytes(message);
// 创建UDP客户端发送数据
UdpClient client = new UdpClient();
client.Send(buffer, buffer.Length, remoteEndPoint);
client.Close();
UDP通信的实现,虽然简洁,但需要注意的是,由于没有建立连接,一旦数据包发出,发送方不会收到任何确认。因此,开发者需要自己实现消息的确认机制,或者采用其他方法确保数据的成功传递。
在后续章节中,我们将继续探讨UDP和TCP的实际应用示例,以及如何在C#中实现这些复杂的网络通信场景。
4. C#源代码示例:TCP和UDP通信
在本章节中,我们将通过示例源代码深入分析如何在C#中实现TCP和UDP通信。我们将从TCP通信的C#源代码实例入手,进而探讨UDP通信的具体实现,为理解和应用这些网络编程技术提供直观的参考。
4.1 TCP通信的C#源代码实例
TCP(Transmission Control Protocol,传输控制协议)是面向连接的、可靠的、基于字节流的传输层通信协议。在C#中,可以通过 System.Net 和 System.Net.Sockets 命名空间中的类实现TCP通信。
4.1.1 服务端代码详解
TCP服务端的核心代码主要涉及以下几个步骤:
- 创建
TcpListener实例,绑定到本地端口,并监听客户端的连接请求。 - 接受客户端的连接请求,创建
TcpClient实例。 - 使用
NetworkStream读取和发送数据。 - 关闭连接和释放资源。
以下是TCP服务端的C#代码示例:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
class TcpServer
{
private TcpListener tcpListener;
public TcpServer(IPAddress localAddr, int port)
{
tcpListener = new TcpListener(localAddr, port);
}
public void Start()
{
tcpListener.Start();
Console.WriteLine("Server started. Waiting for a connection...");
// Buffer for reading data
byte[] bytes = new byte[256];
string data;
// Enter the listening loop
while (true)
{
Console.Write("Waiting for a connection...");
// Perform a blocking call to accept requests. You could also user an asynchronous mechanism to achieve this.
TcpClient client = tcpListener.AcceptTcpClient();
Console.WriteLine("Connected!");
data = null;
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
data = Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
// Process the data sent by the client.
data = data.ToUpper();
// Send back a response.
byte[] msg = Encoding.ASCII.GetBytes(data);
stream.Write(msg, 0, msg.Length);
Console.WriteLine("Sent: {0}", data);
}
// Shutdown and end connection
client.Close();
}
}
}
// 运行服务端的示例
public class Program
{
public static void Main(string[] args)
{
TcpServer server = new TcpServer(IPAddress.Any, 8000);
server.Start();
}
}
在上述代码中,我们首先初始化了一个 TcpListener 对象并开始监听指定的本地地址和端口。当客户端发起连接请求时,我们通过 AcceptTcpClient() 方法接受连接,然后使用 NetworkStream 读取数据。数据读取完成后,我们将其转换为ASCII字符串并转换为大写,最后将处理后的数据发送回客户端。
4.1.2 客户端代码详解
TCP客户端的实现涉及以下步骤:
- 创建
TcpClient实例并尝试连接到服务器。 - 使用
NetworkStream发送和接收数据。 - 关闭连接和释放资源。
以下是一个简单的TCP客户端的C#代码示例:
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
public class TcpClientExample
{
public static void Main()
{
// Create a TcpClient.
TcpClient client = new TcpClient();
// Connect to a remote device.
try
{
client.Connect(IPAddress.Parse("127.0.0.1"), 8000);
Console.WriteLine("Connected to server");
// Get a stream object for reading and writing.
NetworkStream stream = client.GetStream();
// Send data to the connected TcpServer.
string message = "This is a test<EOF>";
byte[] data = Encoding.ASCII.GetBytes(message);
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", message);
// Receive the TcpServer.response.
// Buffer to store the response bytes.
data = new byte[256];
// String to store the response ASCII representation.
string responseData = string.Empty;
// Read the first batch of the TcpServer response bytes.
int bytes = stream.Read(data, 0, data.Length);
responseData = Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}", responseData);
// Close everything.
stream.Close();
client.Close();
}
catch (ArgumentNullException e)
{
Console.WriteLine("ArgumentNullException: {0}", e);
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
Console.WriteLine("\n Press Enter to continue...");
Console.Read();
}
}
在这个客户端示例中,我们首先创建了 TcpClient 的一个实例,并尝试连接到本地主机的8000端口上。连接成功后,我们向服务器发送一条消息,并等待服务器的响应。一旦接收到响应,我们将其输出到控制台,并关闭连接。
4.2 UDP通信的C#源代码实例
UDP(User Datagram Protocol,用户数据报协议)是一种无连接的网络协议,它不需要建立连接就能发送数据包。在C#中实现UDP通信相对简单,因为我们不需要像TCP那样处理连接的建立和断开。
4.2.1 简单的UDP通信示例
下面的C#代码示例展示了一个简单的UDP服务器和客户端的实现:
UDP服务器代码:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
class UdpServer
{
private UdpClient udpServer;
public void Start(int port)
{
udpServer = new UdpClient(port);
Console.WriteLine("UdpServer started...");
try
{
while (true)
{
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, port);
// Wait for data to arrive.
byte[] data = udpServer.Receive(ref remoteEndPoint);
string receivedData = Encoding.ASCII.GetString(data);
Console.WriteLine("Received: {0}", receivedData);
// Echo the data back to the client.
udpServer.Send(data, data.Length, remoteEndPoint);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
udpServer.Close();
}
}
}
class Program
{
static void Main()
{
UdpServer server = new UdpServer();
server.Start(8001);
}
}
UDP客户端代码:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
class UdpClientExample
{
public static void Main()
{
UdpClient client = new UdpClient(8001);
Console.WriteLine("Sending data to server...");
// Set up the remote device to receive data.
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8001);
// Data to be sent.
string message = "This is a test";
byte[] data = Encoding.ASCII.GetBytes(message);
// Send data.
client.Send(data, data.Length, remoteEndPoint);
Console.WriteLine("Sent: {0}", message);
// Get a response from the server.
data = client.Receive(ref remoteEndPoint);
Console.WriteLine("Received: {0}", Encoding.ASCII.GetString(data));
// Close the client.
client.Close();
}
}
在这个简单的UDP通信示例中,UDP服务器等待客户端发送数据,一旦接收到数据就立即回复同样的数据包,这就是所谓的“回声”服务器。UDP客户端发送一个字符串到服务器,并等待服务器的回复。
4.2.2 高级UDP通信示例
在更高级的UDP通信示例中,我们可能会处理多播或广播消息。以下是一个使用UDP实现多播通信的示例代码:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class UdpMulticastExample
{
public static void Main(string[] args)
{
try
{
// Create the UdpClient and join a multicast group
UdpClient client = new UdpClient(8888);
client.JoinMulticastGroup(IPAddress.Parse("239.255.255.250"));
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 8888);
// Create a buffer to hold the response data
byte[] response = new byte[1024];
// Create a buffer to send the data
string sentence = "Hello Multicast";
byte[] data = Encoding.ASCII.GetBytes(sentence);
// Send the data
client.Send(data, data.Length, groupEP);
Console.WriteLine("Sent: " + sentence);
// Block forever to receive data
while (true)
{
Console.WriteLine("Waiting for multicast messages...");
response = client.Receive(ref groupEP);
Console.WriteLine("Received: " + Encoding.ASCII.GetString(response));
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
在上述代码中,客户端创建了一个 UdpClient 实例,并通过调用 JoinMulticastGroup 方法加入了一个多播组。然后,它发送消息到该多播地址并等待接收来自组内其他成员的消息。
本章节通过C#代码实例深入讲解了TCP和UDP通信的实现方式。通过具体的操作步骤和代码解释,我们可以看到网络编程在实际开发中的应用和重要性。下一章节,我们将继续探讨网络通信中的异常处理策略,进一步增强网络通信程序的健壮性。
5. 异常处理策略
5.1 网络通信中的常见异常
网络通信是一个复杂的过程,涉及许多可能的失败点,因此异常处理是确保应用程序鲁棒性的重要组成部分。异常可以分为两大类:同步异常和异步异常。同步异常通常是由于编程错误引起的,比如尝试在不存在的网络资源上执行操作。异步异常则更多地与外部条件相关,如网络中断或服务端关闭。
5.1.1 异常类型和特性
在C#中,网络通信可能会遇到的异常类型主要包括 SocketException 、 ObjectDisposedException 、 IOException 等。 SocketException 是最常见的异常类型,它发生在底层的socket操作失败时。 ObjectDisposedException 则发生在尝试使用已关闭或已销毁的socket时。 IOException 可能在任何I/O操作失败时抛出,特别是在网络通信中断或者缓冲区溢出的情况下。
5.1.2 异常的捕获和处理
异常捕获通常通过 try-catch 语句来完成。网络编程中的最佳实践是尽可能精确地捕获异常类型。这有助于明确处理网络通信失败的代码路径,并提供给开发人员足够的信息来解决问题。处理异常时,务必确保在处理完毕后,相关的网络资源被适当地关闭或清理,以避免内存泄漏。
5.2 C#网络通信异常处理
5.2.1 try-catch-finally语句的使用
在C#网络编程中, try-catch-finally 语句经常被用来捕获和处理异常。 try 块中包含可能会引发异常的代码, catch 块则用于捕获并处理特定类型的异常。无论是否发生异常, finally 块中的代码总是会被执行,通常用于进行资源清理工作。
下面是一个使用 try-catch-finally 的简单示例:
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
// 尝试连接到服务器
socket.Connect(ipAddress, port);
}
catch (SocketException ex)
{
// 捕获并处理SocketException
Console.WriteLine($"SocketException occurred: {ex}");
}
finally
{
// 关闭socket连接,释放资源
socket.Close();
}
在这个例子中,如果在尝试连接到服务器的过程中发生 SocketException ,异常会被捕获并打印错误信息。无论是否发生异常, finally 块都会执行,关闭socket连接。
5.2.2 自定义异常类和异常传播机制
在某些情况下,系统抛出的标准异常不能完全描述问题的细节,这时候就需要创建自定义异常类。自定义异常类应继承自 System.Exception 类,并提供必要的属性和方法来描述特定的错误情况。
异常传播是另一个重要的概念,它描述了异常如何从发生点传播到调用栈的更高层,直到它被适当处理。在C#中,异常传播通常是自动完成的,但是可以通过 throw 语句显式抛出异常。
自定义异常类和异常传播机制的结合使用,可以提高程序的可维护性和可读性,使得错误处理代码更加清晰和有针对性。
通过本章节的介绍,您应该对C#网络通信中可能出现的异常有了全面的了解,同时也掌握了一些基本的异常捕获和处理技巧。了解异常处理的最佳实践对于编写健壮的网络应用程序至关重要。
6. 多线程在C#网络通信中的应用
6.1 多线程编程理论
6.1.1 线程的基本概念
在操作系统中,线程是CPU调度和分派的基本单位,它被包含在进程之中,是进程中的实际运作单位。C#中的线程允许执行程序的多个部分同时运行,这对于网络通信中需要同时处理多个客户端请求非常有用。理解线程的基本概念是掌握多线程编程的前提。
6.1.2 线程的同步与协作
在多线程编程中,线程的同步和协作是关键问题。由于线程可以共享进程的资源,所以必须妥善处理线程间的同步,防止竞态条件和资源冲突。C#提供了多种机制来实现线程同步,例如使用Monitor、Mutex、Semaphore和EventWaitHandle等。
6.2 C#多线程网络通信实践
6.2.1 在C#中创建和管理线程
C#使用 System.Threading 命名空间中的 Thread 类来创建和控制线程。以下是一个简单的示例,展示如何创建和启动一个线程:
using System;
using System.Threading;
class Program
{
static void Main(string[] args)
{
// 创建线程
Thread newThread = new Thread(Work);
// 启动线程
newThread.Start();
Console.WriteLine("主线程: 我将继续执行并等待新线程完成工作。");
// 等待新线程结束
newThread.Join();
Console.WriteLine("所有线程都已结束。");
}
static void Work()
{
Console.WriteLine("新线程: 我是新线程,我开始工作了。");
// 执行线程任务
// 线程结束
Console.WriteLine("新线程: 我的任务完成了。");
}
}
6.2.2 多线程在TCP/UDP通信中的应用案例
在网络通信中,多线程可以用来同时处理多个客户端的连接和请求。例如,使用 Thread 类为每个进入的TCP连接创建一个新线程,或者使用 ThreadPool 类来管理线程池中的线程。
下面是一个简化的TCP服务器示例,它使用多线程来处理每个客户端的请求:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
class TcpServer
{
private TcpListener tcpListener;
public TcpServer(IPAddress ip, int port)
{
tcpListener = new TcpListener(ip, port);
}
public void Start()
{
tcpListener.Start();
Console.WriteLine("服务器启动,等待连接...");
while (true)
{
// 等待连接
TcpClient client = tcpListener.AcceptTcpClient();
Console.WriteLine("连接已建立。");
// 为每个客户端创建一个新的线程
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClient));
clientThread.Start(client);
}
}
private void HandleClient(object obj)
{
TcpClient client = (TcpClient)obj;
NetworkStream stream = client.GetStream();
byte[] buffer = new byte[1024];
int bytesRead;
try
{
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
{
// 处理数据
string message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("客户端: " + message);
// 发送响应
stream.Write(buffer, 0, bytesRead);
}
}
catch (Exception e)
{
Console.WriteLine("处理客户端时发生错误: " + e.Message);
}
finally
{
// 关闭连接
client.Close();
}
}
}
此示例中,服务器在接收到客户端连接后,将为每个连接创建一个新的线程来处理。这允许服务器同时与多个客户端通信。注意,虽然这简化了示例,但实际应用中还需要考虑线程安全性、异常处理和资源管理等问题。
简介:C#通过System.Net.Sockets命名空间下的Socket类提供了强大的网络编程接口,支持TCP和UDP协议进行网络通信。本文将介绍网络通信基础、TCP和UDP协议的特点,并通过C#源代码实例,阐述如何实现客户端和服务器端的TCP和UDP通信。同时,将涉及异常处理、多线程、性能优化、网络套接字选项设置以及安全性策略,帮助开发者在C#中构建高效和稳定的应用程序。

1972

被折叠的 条评论
为什么被折叠?



