在本文中,我们展示了如何使用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#教程。
