ZetCode

C# TcpClient

最后修改于 2023 年 7 月 5 日

C# TcpClient 教程展示了如何使用 C# 中的 TcpClient 创建网络程序。 C# 教程 是关于 C# 语言的综合教程。

C# TcpClient

TcpClient 类提供了用于通过网络连接、发送和接收流数据的简单方法。

C# TcpClient HEAD 请求

HTTP HEAD 方法请求如果使用 HTTP GET 方法请求指定资源会返回的头部信息。

Program.cs
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 = "HEAD / HTTP/1.1\r\nHost: webcode.me\r\nUser-Agent: C# program\r\n"
    + "Connection: close\r\nAccept: text/html\r\n\r\n";

Console.WriteLine(message);

using var reader = new StreamReader(networkStream, Encoding.UTF8);

byte[] bytes = Encoding.UTF8.GetBytes(message);
networkStream.Write(bytes, 0, bytes.Length);

Console.WriteLine(reader.ReadToEnd());

在此示例中,我们向 webcode.me 发送 HEAD 请求。 该请求是同步的。

using var client = new TcpClient();

创建一个新的 TcpClientusing 关键字会在变量超出范围时释放资源。

var hostname = "webcode.me";
client.Connect(hostname, 80);

通过 Connect 方法,我们使用指定的端口连接到站点。

using NetworkStream networkStream = client.GetStream();
networkStream.ReadTimeout = 2000;

我们获取一个 NetworkStream 并设置读取超时。

using var writer = new StreamWriter(networkStream);

创建一个 StreamWriter。 它用于将数据写入创建的网络流。

var message = "HEAD / HTTP/1.1\r\nHost: webcode.me\r\nUser-Agent: C# program\r\n" +
    "Connection: close\r\nAccept: text/html\r\n\r\n";

我们定义一个 HEAD 请求。 HEAD 请求通过 HEAD 命令发出,后跟资源 URL 和 HTTP 协议版本。 请注意,\r\n 字符是语法的一部分。 详细信息在 RFC 7231 文档中描述。

using var reader = new StreamReader(networkStream, Encoding.UTF8);

我们创建一个 StreamReader 来读取响应。

byte[] bytes = Encoding.UTF8.GetBytes(message);
networkStream.Write(bytes, 0, bytes.Length);

文本命令使用 GetBytes 方法转换为字节。 这些字节使用 Write 方法写入网络流。

Console.WriteLine(reader.ReadToEnd());

我们读取响应并将其写入控制台。

$ dotnet run
HEAD / HTTP/1.1
Host: webcode.me
User-Agent: C# program
Connection: close
Accept: text/html


HTTP/1.1 200 OK
Server: nginx/1.6.2
Date: Tue, 12 Jul 2022 18:49:44 GMT
Content-Type: text/html
Content-Length: 394
Last-Modified: Sun, 23 Jan 2022 10:39:25 GMT
Connection: close
ETag: "61ed305d-18a"
Accept-Ranges: bytes

C# TcpClient GET 请求

HTTP GET 方法请求指定资源的表示形式。

Program.cs
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: C# program
Connection: close
Host: webcode.me" + "\r\n\r\n";

Console.WriteLine(message);

using var reader = new StreamReader(networkStream, Encoding.UTF8);
byte[] bytes = Encoding.UTF8.GetBytes(message);

networkStream.Write(bytes, 0, bytes.Length);
Console.WriteLine(reader.ReadToEnd());

该示例检索指定网站的主页。

var message = @"GET / HTTP/1.1
Accept: text/html, charset=utf-8
Accept-Language: en-US
User-Agent: C# program
Connection: close
Host: webcode.me" + "\r\n\r\n";

我们定义一个 GET 请求。

$ dotnet run
GET / HTTP/1.1
Accept: text/html, charset=utf-8
Accept-Language: en-US
User-Agent: C# program
Connection: close
Host: webcode.me


HTTP/1.1 200 OK
Server: nginx/1.6.2
Date: Tue, 12 Jul 2022 19:29:46 GMT
Content-Type: text/html
Content-Length: 394
Last-Modified: Sun, 23 Jan 2022 10:39:25 GMT
Connection: close
ETag: "61ed305d-18a"
Access-Control-Allow-Origin: *
Accept-Ranges: bytes

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My html page</title>
</head>
<body>

    <p>
        Today is a beautiful day. We go swimming and fishing.
    </p>

    <p>
         Hello there. How are you?
    </p>

</body>
</html>

TcpClient POST 请求

POST 请求将数据发送到服务器。 使用 Content-Type 标头字段,我们告诉服务器发送的是什么类型的数据。 使用 application/x-www-form-urlencoded 选项,数据在请求的正文中发送; 键和值在键值对中编码,由 '&' 分隔,键和值之间用 '=' 分隔。 此类型不适合传输二进制数据,因为键和值中的非字母数字字符都经过百分比编码。

Program.cs
using System.Text;
using System.Net.Sockets;

using var client = new TcpClient();

var hostname = "httpbin.org";
client.Connect(hostname, 80);

using NetworkStream networkStream = client.GetStream();
networkStream.ReadTimeout = 2000;

var data = "name=John+Doe&occupation=gardener";
var n = data.Length;

var message = @$"POST /anything HTTP/1.1
Accept: */*
Accept-Language: en-US
User-Agent: C# program
Host: httpbin.org
Content-Type: application/x-www-form-urlencoded
Content-Length: {n}
Connection: close"
+ "\r\n\r\n" + data;

Console.WriteLine(message);

using var reader = new StreamReader(networkStream, Encoding.UTF8);
byte[] bytes = Encoding.UTF8.GetBytes(message);

networkStream.Write(bytes, 0, bytes.Length);

Console.WriteLine("---------------------");

Console.WriteLine(reader.ReadToEnd());

此示例发送 POST 请求。 它在其正文中包含 URL 编码的数据。

var data = "name=John+Doe&occupation=gardener";
var n = data.Length;

这是要发送的数据。 我们也需要它的长度。

var message = @$"POST /anything HTTP/1.1
Accept: */*
Accept-Language: en-US
User-Agent: C# program
Host: httpbin.org
Content-Type: application/x-www-form-urlencoded
Content-Length: {n}
Connection: close"
+ "\r\n\r\n" + data;

我们构造一个 POST 请求。 我们必须设置 Content-TypeContent-Length 标头字段。 标头和数据必须用 \r\n\r\n 字符分隔。

$ dotnet run
POST /anything HTTP/1.1
Accept: */*
Accept-Language: en-US
User-Agent: C# program
Host: httpbin.org
Content-Type: application/x-www-form-urlencoded
Content-Length: 33
Connection: close

name=John+Doe&occupation=gardener
---------------------
HTTP/1.1 200 OK
Date: Wed, 13 Jul 2022 09:54:51 GMT
Content-Type: application/json
Content-Length: 521
Connection: close
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "name": "John Doe", 
    "occupation": "gardener"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Language": "en-US", 
    "Content-Length": "33", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "C# program", 
    "X-Amzn-Trace-Id": "Root=1-62ce966b-112441ca5298988e4cb6ebee"
  }, 
  "json": null, 
  "method": "POST", 
  "origin": "188.167.250.179", 
  "url": "http://httpbin.org/anything"
}

C# TcpClient 异步请求

在以下示例中,我们创建一个异步请求。

Program.cs
using System.Net.Sockets;


string host = "webcode.me";
int port = 80;
int timeout = 5000;

using var client = new TcpClient();

await client.ConnectAsync(host, port);

using var netstream = client.GetStream();
using var writer = new StreamWriter(netstream);
using var reader = new StreamReader(netstream);

writer.AutoFlush = true;
netstream.ReadTimeout = timeout;

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";

await writer.WriteLineAsync(message);

string response = await reader.ReadToEndAsync();
Console.WriteLine($"Server: {response}");

该示例创建一个对 webcode.me 的异步 GET 请求。

await client.ConnectAsync(host, port);

我们异步连接到服务器。

await writer.WriteLineAsync(message);

我们使用 WriteLineAsync 异步写入网络流。

string response = await reader.ReadToEndAsync();

我们使用 ReadToEndAsync 异步地从网络流中读取。

来源

TcpClient 类 - 语言参考

在本文中,我们使用了 C# TcpClient。

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直在撰写编程文章。 迄今为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 C# 教程