C# 使用TCP创建HTTP客户程序

04cd7c2576c2ef8257c35efc8a5d6cae.png

首先,创建一个控制台应用程序(包),向 Web 服务器发送一个 HTTP 请求。以前用 HttpClient 类实现了这个功能,但使用 TcpClient 类需要深入 HTTP 协议。

HttpClientUsingTcp 示例代码使用了以下名称空间:

System 
System.IO
System.Net.Sockets 
System.Text
System.Threading.Tasks

b466748e130fbd09ff41b603de0b7069.png

应用程序接受一个命令行参数,传递服务器的名称。这样,就调用RequestHtmlAsync 方法,向服务器发出 HTTP 请求。它用 Task 的 Result 属性返回一个字符串:

static void Main(string[] args)
{if (args.Length != 1){ShowUsage();}Task<string> tl = RequestHtmlAsync(args[0]); Console.WriteLine(t1.Result); Console.ReadLine();
}private static void ShowUsage()
{Console.WriteLine("Usage: HttpClientUsingTcp hostname");
}

221c205e3bb18bb44fcef4d86f9652f3.png

现在看看 RequestHtmlAsync 方法的最重要部分。首先,实例化一个 TcpClient 对象。其次,使用 ConnectAsync 方法,在 HTTP 默认端口 80 上建立到主机的TCP 连接。再次,通过 GetStream 方法检索一个流,使用这个连接进行读写:

private const int ReadBufferSize = 1024;
public static async Task<string> RequestHtmlAsync(string hostname)
{try{using (var client = new TcpClient()){await client.ConnectAsync(hostname, 80); NetworkStream stream = client.GetStream();//...}}
}

2849937e23a867cb22f4f5cbb7b1238d.png

流现在可以用来把请求写到服务器,读取响应。HTTP 是一种基于文本的协议,所以很容易在字符串中定义请求。为了向服务器发出一个简单的请求,标题定义了 HTTP 方法 GET,其后是 URL/ 的路径和 HTTP 版本 HTTP/1.1。第二行定义了 Host 标题、主机名和端口号,第三行定义了 Connection 标题。通常,通过Connection 标题,客户端请求 keep-alive,要求服务器保持连接打开,因为客户端希望发出更多的请求。这里只向服务器发出一个请求,所以服务器应该关闭连接,从而 close 设置为 Connection 标题。为了结束标题信息,需要使用 \r\n 给请求添加一个空行。标题信息调用 NetworkStream 的方法 WriteAsync,用UTF-8 编码发送。\r\n 为了立即向服务器发送缓存,请调用 FlushAsync 方法。否则数据就可能保存在本地缓存:

//...
string header = "GET/HTTP/1.1\r\n" +
$"Host: {hostname}:80\r\n" +
"Connection: close\r\n" +
"\r\n";
byte[] buffer = Encoding.UTF8.GetBytes(header); 
await stream.WriteAsync(buffer, 0, buffer.Length); 
await stream.FlushAsync();

b32cad8ddbd9a03b214e1deb1c2a04a4.png

现在可以继续这个过程,从服务器中读取回应。不知道回应有多大,所以创建一个动态生长的 MemoryStream。使用 ReadAsync 方法把服务器的回应暂时写入一个字节数组,这个字节数组的内容添加到 MemoryStream 中。从服务器中读取所有数据后,StreamReader 接管控制,把数据从流读入一个字符串,并返回给调用者:

var ms = new MemoryStream();
buffer = new byte[ReadBufferSize]; 
int read = 0; 
do
{read = await stream.ReadAsync(buffer, 0, ReadBufferSize); ms.Write(buffer, 0, read);Array.Clear(buffer, 0, buffer.Length);} while (read > 0);ms.Seek(0, SeekOrigin.Begin);var reader = new StreamReader(ms); return reader.ReadToEnd();
}
//...

1

95366eff627ecb095e20892196165ecd.png

把一个网站传递给程序,会看到一个成功的请求,其 HTML 内容显示在控制台上。现在该创建一个 TCP 侦听器和自定义协议了。

c9818f4cbf5b62e4ce5bae0ff76353e1.png

6c242a1153b81f86237bc42e7ef20633.png

 微信公众号 

Dotnet

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/289267.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

迅捷路由器 服务器无响应,如果路由器重启还是上不了网 几招搞定

如果网速很慢重启了路由器之后结果还是慢&#xff0c;而且甚至上不了网了那该怎么办。如果有这种情况原因其实有很多很多的可能&#xff0c;需要逐个排查&#xff0c;首先需要进入192.168.1.1路由器的管理设置界面&#xff0c;查看路由器的运行状态。路由器设置、路由器没有成功…

Azure DevOps 中 Dapr项目自动部署流程实践

注&#xff1a;本文中主要讨论 .NET6.0项目在 k8s 中运行的 Dapr 的持续集成流程, 但实际上不是Dapr的项目部署到K8s也是相同流程&#xff0c;只是k8s的yaml配置文件有所不同流程选择基于 Dapr 的项目持续集成包含以下流程编译并打包项目构建 Dockerfile,并推送镜像push image至…

React Native之js同步调用安卓原生方法@ReactMethod(isBlockingSynchronousMethod = true)

1 问题 之前的代码js调用安卓原生都是用的异步方法,比如callback, promiss,异步的话,我们一般是在安卓原生有耗时操作,才用异步,如果我要离开返回,就需要js调用安卓同步方法 利用callback实现js调用原生可以参考我的这篇博客 React Native实现js调用安卓原生代码 React Nat…

用POP动画引擎实现弹簧动画(POPSpringAnimation)

效果图: #import "ViewController.h" #import <POP.h>interface ViewController ()property (nonatomic, weak) UIView *testView;endimplementation ViewController- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor [UIColor blackColor…

地理知识归纳:影响降水的九大因素

降水指大气中水汽凝结降落的过程,包括降雨、下雪、冰雹等形式,降水的多少要受很多因素的影响,但主要条件是三个:充足的水汽供应,气流上升达到过饱和状态,足够的凝结核。通常情况下,我们不需要考虑凝结核的问题,只是考虑有没有充足的水汽和促使气流上升的机制就可以,归…

linux 查看cpu_作为高级Java,你应该了解的Linux知识

作为一个javaer&#xff0c;我以前写过很多关于Linux的文章。但经过多年的观察&#xff0c;发现其实对于大部分人&#xff0c;有些东西压根就用不着。用的最多的&#xff0c;就是到线上排查个问题而已&#xff0c;这让人很是苦恼。那么&#xff0c;我们就将范围再缩小一下。最有…

layer和3D仿射变换

1、视图的显示基于图层&#xff0c;通过控制图层同样能控制显示效果&#xff0c;获取当前的视图的layer,并为其增加圆角边框。 //设置layer边框的宽度为2view.layer.borderWidth2;//如果需要为layer添加颜色需要转换为CGColor对象view.layer.borderColor[UIColor greenColor].C…

React Native之Android原生通过DeviceEventEmitter发送消息给js

1 问题 Android原生向js发消息,并且可以携带数据 2 实现原理 Android原生可以使用RCTEventEmitter来注册事件,然后这里需要指定事件的名字,然后在js那端进行监听同样事件的名字监听,就可以收到消息得到数据 Android注册关键代码 reactContext.getJSModule(DeviceEventManag…

CentOS安装JAVA JDK

普通情况下&#xff0c;我们都要将linux自带的OPENJDK卸载掉。然后安装SUN的JDK。首先查看Linux自带的JDK是否已安装。 输入例如以下命令&#xff0c;查看已经安装的JAVA版本号信息。 Linux代码 java -version 输入例如以下命令。查看JDK的信息。Linux代码 rpm -qa|grep j…

安装bigdesk后es无法启动_安装天正后,探索者无法双击启动?

用户经常会出现&#xff0c;安装天正后&#xff0c;探索者无法双击启动&#xff0c;或者是图纸无法拖拽入CAD中&#xff0c;如何解决&#xff1f;答&#xff1a;天正安装完成后&#xff0c;默认将CAD的acad.exe程序&#xff0c;添加了“以管理员身份运行此程序”而导致的&#…

服务器安全维护包含,服务器安全维护包含

服务器安全维护包含 内容精选换一换本章节介绍如何使用管理控制台向导创建裸金属服务器。创建裸金属服务器时&#xff0c;您需要配置规格、镜像、存储、网络、安全组等必备信息。同时&#xff0c;向导也提供了丰富的扩展配置功能&#xff0c;方便您进行个性化部署和管理。在创建…

C# 发出异步的Get请求

下列的下载代码示例是 HttpClientSample。它以不同的方式异步调用Web 服务。为了演示本例使用的不同方法&#xff0c;使用了命令行参数。示例代码使用了以下名称空间&#xff1a;System System.Linq System.Net System.Net.Http System.Net.Http.Headers System.Threading Sy…

React Native之Props(属性)和State(状态)和简单样式简单使用

1 Props(属性)和State(状态)和简单样式简单使用App.js代码如下 /*** Sample React Native App* https://github.com/facebook/react-native** format* flow*/import React, {Component} from react; import {Platform, StyleSheet, Text, View, NativeModules, DeviceEvent…

config kubectl_Kubernetes(k8s)中文文档 kubectl config set-context_Kubernetes中文社区

译者&#xff1a;hurf在kubeconfig配置文件中设置一个环境项。摘要在kubeconfig配置文件中设置一个环境项。 如果指定了一个已存在的名字&#xff0c;将合并新字段并覆盖旧字段。kubectl config set-context NAME [--clustercluster_nickname] [--useruser_nickname] [--namesp…

使用基于Roslyn的编译时AOP框架来解决.NET项目的代码复用问题

理想的代码优化方式团队日常协作中&#xff0c;自然而然的会出现很多重复代码&#xff0c;根据这些代码的种类&#xff0c;之前可能会以以下方式处理方式描述应用时可能产生的问题硬编码多数新手&#xff0c;或逐渐腐坏的项目会这么干&#xff0c;会直接复制之前实现的代码带来…

React Native之Flexbox布局和监测文本输入onChangeText

1 Flexbox布局 1) flexDirection 可以决定布局的主轴,子元素是应该沿着水平轴(row)方向排列&#xff0c;还是沿着竖直轴(column)方向排列 2) justifyContent 决定其子元素沿着次轴&#xff08;与主轴垂直的轴&#xff0c;比如若主轴方向为row&#xff0c;则次轴方向为…

半年总结——欲戴王冠,必承其重

【Introduction】 每一个女生都梦想着作为一个女王。但是你仅仅看到了女王头上金闪闪的王冠&#xff0c;却不知道在这个王冠下。她是怎样成长的&#xff01;假设你想要做到有女王一样的权利&#xff0c;就必需要承担一个女王应该做到的事情&#xff01;——欲带王冠&#xff0c…

一维数组和二维数组的区别_数组指针和指针数组的区别

数组指针和指针数组的区别 - hongcha_717 - 博客园​www.cnblogs.com数组指针&#xff08;也称行指针&#xff09;定义 int (*p)[n];()优先级高&#xff0c;首先说明p是一个指针&#xff0c;指向一个整型的一维数组&#xff0c;这个一维数组的长度是n&#xff0c;也可以说是p的…

mysql 配置多个数据库连接_总结MySQL修改最大连接数的两个方式

问题在使用MySQL数据库的时候&#xff0c;经常会遇到这么一个问题&#xff0c;就是“Can not connect to MySQL server. Too many connections”-mysql 1040错误&#xff0c;这是因为访问MySQL且还未释放的连接数目已经达到MySQL的上限。通常&#xff0c;mysql的最大连接数默认…

饿了么超级会员,年卡低至108元!饿了么会员,点外卖超省钱!

饿了么是大家常用的外卖平台&#xff0c;经常点外卖的朋友&#xff0c;充个饿了么超级吃货卡&#xff0c;还是能省不少钱的&#xff0c;今天给大家带来饿了么会员特价充值&#xff0c;会员秒到&#xff01;饿了么超级会员特价充值月卡&#xff1a;原价15元&#xff0c;特价仅需…