在本文中,我们展示了如何使用C#创建基本的网络程序。
System.Net
命名空间为当今网络上使用的许多协议提供了一个简单的编程接口。
C#URI
Uri
提供统一资源标识符(URI)的对象表示以及对URI各部分的轻松访问。
var resource = "http://webcode.me:80/"; var resource2 = "http://webcode.me/index.html"; var resource3 = "http://www.webcode.me/name=Peter&age=23"; var path = new Uri(resource); var path2 = new Uri(resource2); var path3 = new Uri(resource3); Console.WriteLine(path.Port); Console.WriteLine(path.Host); Console.WriteLine(path.Authority); Console.WriteLine(path.LocalPath); Console.WriteLine(path.Scheme); Console.WriteLine("-----------------------"); Console.WriteLine(path2.Port); Console.WriteLine(path2.LocalPath); Console.WriteLine("-----------------------"); Console.WriteLine(path3.Authority); Console.WriteLine(path3.PathAndQuery); Console.WriteLine(path3.Query); Console.WriteLine(path3.AbsolutePath); Console.WriteLine(path3.AbsoluteUri);
在此示例中,我们使用Uri
类。
var resource = "http://webcode.me:80/"; var resource2 = "http://webcode.me/index.html"; var resource3 = "http://www.webcode.me/name=Peter&age=23";
我们定义了三个资源路径。
var path = new Uri(resource); var path2 = new Uri(resource2); var path3 = new Uri(resource3);
根据路径,我们创建网络资源。
Console.WriteLine(path.Port); Console.WriteLine(path.Host); Console.WriteLine(path.Authority); Console.WriteLine(path.LocalPath); Console.WriteLine(path.Scheme);
这里我们打印一个Uri
的各个部分。
$ dotnet run 80 webcode.me webcode.me / http ----------------------- 80 /index.html ----------------------- www.webcode.me /name=Peter&age=23 /name=Peter&age=23 http://www.webcode.me/name=Peter&age=23
C#UriBuilder
UriBuilder
提供了一种方便的方法来修改Uri
实例的内容,而无需为每次修改创建新的Uri
实例。
using System.Net; var uriBuilder = new UriBuilder(); uriBuilder.Scheme = "http"; uriBuilder.Host = "webcode.me"; uriBuilder.Path = "/"; Uri uri = uriBuilder.Uri; WebRequest request = WebRequest.Create(uri); using WebResponse response = request.GetResponse(); var headers = response.Headers; Console.WriteLine(headers);
该示例使用UriBuilder
构建一个Uri,并对资源发出一个简单的GET请求。
var uriBuilder = new UriBuilder(); uriBuilder.Scheme = "http"; uriBuilder.Host = "webcode.me"; uriBuilder.Path = "/"; Uri uri = uriBuilder.Uri;
我们使用UriBuilder
构建Uri
。
WebRequest request = WebRequest.Create(uri);
我们使用WebRequest
创建对Uri的网络请求。
using WebResponse response = request.GetResponse();
使用GetResponse
方法,我们向Uri
指定的资源发出同步请求。
var headers = response.Headers; Console.WriteLine(headers);
从响应中,我们获取标头并将它们打印到控制台。
$ dotnet run Server: nginx/1.6.2 Date: Wed, 10 Feb 2021 12:42:16 GMT Connection: keep-alive ETag: "5d32ffc5-15c" Access-Control-Allow-Origin: * Accept-Ranges: bytes Content-Type: text/html Content-Length: 348 Last-Modified: Sat, 20 Jul 2019 11:49:25 GMT
我们看到服务器响应我们请求的标头。
C#主机名
Dns.GetHostName
方法获取本地计算机的主机名。
using System.Net; var hostName = Dns.GetHostName(); Console.WriteLine($"Hostname: {hostName}");
该程序打印出我们本地计算机的主机名。
$ dotnet run Hostname: LAPTOP-OBLOFB9J
C#Dns.GetHostAddresses
Dns.GetHostAddresses
返回一个IPAddress类型的数组,其中包含主机的IP地址。
using System.Net; var hostname = "something.com"; IPAddress[] addresses = Dns.GetHostAddresses(hostname); foreach (IPAddress address in addresses) { Console.WriteLine($"{address}"); }
该示例打印网页的所有IP地址。
$ dotnet run 2606:4700:3033::ac43:b7a8 2606:4700:3031::6815:3bce 172.67.183.168 104.21.59.206
C#GetHostEntry
使用Dns.GetHostEntry
方法,我们可以根据主机名确定IP地址。
using System.Net; var name = "wikipedia.org"; IPHostEntry host = Dns.GetHostEntry(name); var addresses = host.AddressList; foreach (var address in addresses) { Console.WriteLine($"{address}"); }
该示例打印了wikipedia.org
网站的IP地址。
var addresses = host.AddressList;
AddressList
属性包含与主机关联的IP地址列表。
$ dotnet run 2620:0:862:ed1a::1 91.198.174.192
输出由IPv6和IPv4地址组成。
C#平
Ping是一种网络管理实用程序,用于测试Internet协议(IP)网络上主机的可用性。Ping通过向目标主机发送Internet控制消息协议(ICMP)回显请求数据包并等待ICMP回显回复来工作。该程序报告错误、数据包丢失和结果的统计摘要。
.NET包含用于发送ping请求的Ping
类。Ping类使用PingReply
类的实例来返回有关操作的信息并接收回复。
using System.Net.NetworkInformation; using var ping = new Ping(); PingReply reply = ping.Send("192.168.0.23", 100); if (reply.Status == IPStatus.Success) { var msg = @$"Status: {reply.Status} IP Address:{reply.Address} Time:{reply.RoundtripTime}ms"; Console.WriteLine(msg); } else { Console.WriteLine(reply.Status); }
我们向本地lan上的主机发送Ping请求。
PingReply reply = ping.Send("192.168.0.23", 100);
Send
方法尝试发送ICMP回显消息。第二个参数是超时时间。
$ dotnet run Status: Success IP Address:192.168.0.23 Time:4ms
C#套接字
在编程中,套接字是网络上运行的两个程序之间通信的端点。套接字用于在客户端程序和服务器程序之间创建连接。
System.Net.Sockets.Socket
类实现了Berkeley套接字接口。
using System.Text; using System.Net; using System.Net.Sockets; string server = "webcode.me"; int port = 80; var request = $"GET / HTTP/1.1\r\nHost: {server}\r\nConnection: Close\r\n\r\n"; Byte[] requestBytes = Encoding.ASCII.GetBytes(request); Byte[] bytesReceived = new Byte[256]; IPHostEntry hostEntry = Dns.GetHostEntry(server); var ipe = new IPEndPoint(hostEntry.AddressList[0], port); using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(ipe); if (socket.Connected) { Console.WriteLine("Connection established"); } else { Console.WriteLine("Connection failed"); return; } socket.Send(requestBytes, requestBytes.Length, 0); int bytes = 0; var sb = new StringBuilder(); do { bytes = socket.Receive(bytesReceived, bytesReceived.Length, 0); sb.Append(Encoding.ASCII.GetString(bytesReceived, 0, bytes)); } while (bytes > 0); Console.WriteLine(sb.ToString());
该示例使用Socket
类将数据发送到HTTP服务器并接收响应。此示例会阻塞,直到接收到整个页面。请注意,套接字编程是低级的。HttpWebRequest
或HttpClient
等类抽象出这些低级细节。
string server = "webcode.me"; int port = 80;
我们定义服务器和端口。
var request = $"GET / HTTP/1.1\r\nHost: {server}\r\nConnection: Close\r\n\r\n";
我们定义了一个GET请求。GET请求使用GET命令发出,后跟资源URL和HTTP协议版本。请注意,\r\n
字符是通信过程的必需部分。详细信息在RFC7231文档中进行了描述。
Byte[] requestBytes = Encoding.ASCII.GetBytes(request);
我们将请求的文本数据转换为字节。
Byte[] bytesReceived = new Byte[256];
此字节数组用于存储来自服务器的数据。
IPHostEntry hostEntry = Dns.GetHostEntry(server);
通过Dns.GetHostEntry
我们可以找到域名的IP地址。
var ipe = new IPEndPoint(hostEntry.AddressList[0], port);
我们创建一个IPEndPoint
;它是一个网络端点,由IP地址和端口号组成。IP地址是从AddressList
属性中检索的。
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
一个新的TCP套接字被创建。AddressFamily.InterNetwork
指定我们使用IPv4地址。SocketType.Stream
提供可靠的、双向的、基于连接的字节流。ProtocolType.Tcp
确定协议类型。
socket.Connect(ipe);
我们使用Connect
方法连接到具有给定IPEndPoint
的网络端点。
if (socket.Connected) { Console.WriteLine("Connection established"); } else { Console.WriteLine("Connection failed"); return; }
我们检查是否已成功连接。
socket.Send(requestBytes, requestBytes.Length, 0);
我们使用Send
方法向服务器发送请求。
do { bytes = socket.Receive(bytesReceived, bytesReceived.Length, 0); sb.Append(Encoding.ASCII.GetString(bytesReceived, 0, bytes)); } while (bytes > 0);
我们使用Receive
方法从套接字中获取数据。我们使用GetString
方法将字节转换为文本,并将文本数据添加到StringBuilder
中。
Console.WriteLine(sb.ToString());
最后将文本数据写入控制台。
C#UdpClient
UdpClient
提供用户数据报协议(UDP)网络服务。它包含以阻塞同步模式发送和接收无连接UDP数据报的方法。我们不需要在发送和接收数据之前建立远程主机连接,因为UDP是一种无连接传输协议,
出于安全考虑,大多数公共服务器不再提供回显服务。为了测试示例,我们需要在本地lan上设置服务器并启用xinetd
(Debian)或inetd
(FreeBSD)守护程序。
using System.Text; using System.Net; using System.Net.Sockets; UdpClient udpClient = new UdpClient("core9", 7); Byte[] data = Encoding.ASCII.GetBytes("Hello there"); udpClient.Send(data, data.Length); IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); Byte[] received = udpClient.Receive(ref RemoteIpEndPoint); string output = Encoding.ASCII.GetString(received); Console.WriteLine(output); udpClient.Close();
该示例将消息发送到回显服务。这是一个用于测试目的的简单服务。echo服务在端口7上侦听。请注意,该服务可以在TCP或UDP上运行。
$ dotnet run Hello there
我们发送的消息被回显给我们。
C#客户端
TcpClient
类使用TCP从Internet资源请求数据。TcpClient
抽象了创建Socket
以通过TCP请求和接收数据的底层细节。
由于与远程设备的连接表示为流,因此可以使用.NET流处理技术读取和写入数据。
using System.Text; using System.Net.Sockets; using var client = new TcpClient(); var hostname = "webcode.me"; client.Connect(hostname, 80); using NetworkStream networkStream = client.GetStream(); networkStream.ReadTimeout = 2000; var message = @"GET / HTTP/1.1 Accept: text/html, charset=utf-8 Accept-Language: en-US User-Agent: Console app Connection: close Host: webcode.me" + "\r\n\r\n"; using var reader = new StreamReader(networkStream, Encoding.UTF8); byte[] bytes = Encoding.UTF8.GetBytes(message); networkStream.Write(bytes, 0, bytes.Length); Console.WriteLine(reader.ReadToEnd());
该示例使用TcpClient
创建一个GET请求。
using var client = new TcpClient(); var hostname = "webcode.me"; client.Connect(hostname, 80);
一个TCP客户端被创建。我们使用Connect
方法连接到远程主机。
using NetworkStream networkStream = client.GetStream(); networkStream.ReadTimeout = 2000;
使用GetStream
方法,我们获取网络流。我们将超时设置为两秒。
var message = @"GET / HTTP/1.1 Accept: text/html, charset=utf-8 Accept-Language: en-US User-Agent: Console app Connection: close Host: webcode.me" + "\r\n\r\n";
我们构建GET请求消息。不支持持久连接的HTTP/1.1应用程序必须在每条消息中包含close
连接选项。
using var reader = new StreamReader(networkStream, Encoding.UTF8); byte[] bytes = Encoding.UTF8.GetBytes(message);
对于来自服务器的响应,我们创建了一个StreamReader
。我们使用GetBytes
方法将文本数据转换为字节。
networkStream.Write(bytes, 0, bytes.Length);
我们使用Write
方法将消息写入网络流。
Console.WriteLine(reader.ReadToEnd());
我们使用ReadToEnd
方法读取响应。
C#FtpWebRequest
FtpWebRequest
实现文件传输协议(FTP)客户端。
using System.Net; string uri = "ftp://192.168.0.21"; FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(uri); ftpRequest.Credentials = new NetworkCredential("user7", "s$cret"); ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory; using FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse(); using var streamReader = new StreamReader(response.GetResponseStream()); var content = new List<string>(); string line = streamReader.ReadLine(); while (!string.IsNullOrEmpty(line)) { content.Add(line); line = streamReader.ReadLine(); } foreach (var el in content) { Console.WriteLine(el); }
该示例列出了FTP目录中的内容。
string uri = "ftp://192.168.0.21";
这是本地FTP服务器上的URL路径。
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(uri);
根据URI,我们创建FtpWebRequest
。
ftpRequest.Credentials = new NetworkCredential("user7", "s$cret"); ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory;
我们提供凭据和FTP方法;我们将列出内容或目录。
using FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse(); using var streamReader = new StreamReader(response.GetResponseStream());
我们得到一个响应并创建一个流阅读器来读取它。
var content = new List<string>(); string line = streamReader.ReadLine(); while (!string.IsNullOrEmpty(line)) { content.Add(line); line = streamReader.ReadLine(); }
数据被读入列表。
foreach (var el in content) { Console.WriteLine(el); }
最后,内容打印到控制台。
C#SmtpClient
SmtpClient
允许应用程序使用简单邮件传输协议(SMTP)发送电子邮件。
请注意,该类已标记为过时,建议使用MailKit库来处理电子邮件。
using System.Net.Mail; var client = new SmtpClient("core9", 25); using var msg = new MailMessage(); msg.From = new MailAddress("john.doe@example.com"); msg.Subject = "Hello"; msg.Body = "hello there"; msg.To.Add(new MailAddress("root@core9")); client.Send(msg);
该示例向本地网络上的服务器发送一封简单的邮件。
C#HttpClient
HttpClient
是一个基类,用于从URI标识的资源发送HTTP请求和接收HTTP响应。
using var client = new HttpClient(); var result = await client.GetAsync("http://webcode.me"); Console.WriteLine(result.StatusCode);
该示例创建了一个对小型网站的GET请求。我们得到请求的状态码。
using var client = new HttpClient();
创建了一个新的HttpClient
。
var result = await client.GetAsync("http://webcode.me");
GetAsync
方法将GET请求作为异步操作发送到指定的Uri。await
运算符暂停对封闭异步方法的计算,直到异步操作完成。当异步操作完成时,await
运算符返回操作结果(如果有)。
$ dotnet run OK
我们得到200OK状态码;网站上线了。
C#HttpListener
HttpListener
是一个简单的、以编程方式控制的HTTP协议侦听器。
using System.Net; using System.Text; using var listener = new HttpListener(); listener.Prefixes.Add("http://localhost:8001/"); listener.Start(); Console.WriteLine("Listening on port 8001..."); while (true) { HttpListenerContext context = listener.GetContext(); HttpListenerRequest req = context.Request; using Stream ris = req.InputStream; using StreamReader sr = new StreamReader(ris, Encoding.UTF8); string doc = sr.ReadToEnd(); Console.WriteLine($"Received request for {req.Url}"); Console.WriteLine(doc); HttpListenerResponse resp = context.Response; string data = "Hello there!"; byte[] buffer = Encoding.UTF8.GetBytes(data); resp.ContentLength64 = buffer.Length; Stream ros = resp.OutputStream; ros.Write(buffer, 0, buffer.Length); ros.Close(); }
该示例创建了一个简单的HTTP服务器。
using var listener = new HttpListener(); listener.Prefixes.Add("http://localhost:8001/"); listener.Start();
我们创建一个侦听端口8001的侦听器。
HttpListenerContext context = listener.GetContext(); HttpListenerRequest req = context.Request;
使用GetContext
,我们等待传入请求并在收到请求时返回。
using Stream ris = req.InputStream; using StreamReader sr = new StreamReader(ris, Encoding.UTF8); string doc = sr.ReadToEnd(); Console.WriteLine($"Received request for {req.Url}"); Console.WriteLine(doc);
服务器将请求记录到终端。
HttpListenerResponse resp = context.Response; string data = "Hello there!"; byte[] buffer = Encoding.UTF8.GetBytes(data); resp.ContentLength64 = buffer.Length;
我们构建响应对象。
Stream ros = resp.OutputStream; ros.Write(buffer, 0, buffer.Length);
服务器使用Write
将数据写入响应输出流。
在本文中,我们使用C#创建了一些基本的网络程序。
列出所有C#教程。