本鱼拟成立工作室承接项目开发/软件定制/云设施开发运维/办公设备技术支持等,如您有相关需求,欢迎来询 | ::博客文章推荐::

原创FSLib.Network库(目前专注于HTTP的高性能高易用性网络库)

: DOT.NET 木魚 38619℃ 69评论

FSLIB.NETWORK网络库系列文章

  1. 12306订票助手.NET V10.6.1 发布8年前 (2016-09-01)
  2. 开源 FSLIB.NETWORK 库 2.2.0.08年前 (2016-08-02)
  3. FSLIB.NETWORK手册(1) · 基本概念和流程8年前 (2016-05-05)
  4. 原创FSLib.Network库更新 2.0.0 版8年前 (2016-04-05)
  5. 原创FSLib.Network库更新 1.6.0版(目前专注于HTTP的高性能高易用性网络库)9年前 (2015-12-13)
  6. 玩具系列:批量QQ群签到工具v2 (暂时屏蔽自定义位置功能)9年前 (2015-08-29)
  7. 玩具系列:批量QQ群签到工具(支持自定义位置)9年前 (2015-08-28)
  8. 12306订票助手.NET 8.0.8 发布9年前 (2015-08-21)
  9. 12306订票客户端 FOR .NET 演示项目 【7】登录9年前 (2015-08-18)
  10. 12306订票客户端 FOR .NET 演示项目 【6】验证码输入9年前 (2015-08-12)
  11. 12306订票客户端 FOR .NET 演示项目 【5】获得余票数据9年前 (2015-06-10)
  12. 原创FSLib.Network库发布 1.5 版9年前 (2015-06-09)
  13. 12306订票客户端 FOR .NET 演示项目 【4】界面框架&基础数据初始化9年前 (2015-06-08)
  14. 12306订票客户端 FOR .NET 演示项目 【3】流程分析和项目规划9年前 (2015-05-28)
  15. 12306订票客户端 FOR .NET 演示项目 【2】准备工具9年前 (2015-05-22)
  16. 12306订票客户端 FOR .NET 演示项目 【1】项目概况9年前 (2015-05-19)
  17. 原创FSLib.Network库发布 1.4 版9年前 (2015-05-08)
  18. 放一个抓取网页的信息监控小工具源码9年前 (2015-04-27)
  19. FSLib.Network网络库使用教程[2] 实例教程·美女们快到硬盘里来!10年前 (2015-01-30)
  20. FSLib.Network网络库使用教程[1] 基本使用10年前 (2015-01-19)
  21. 原创FSLib.Network库(目前专注于HTTP的高性能高易用性网络库)10年前 (2015-01-18)

0.背景

开始在设计订票助手.NET的时候,我就在策划写一个比较易用的HTTP客户端库来完成底层的操作。由于.NET原生的HttpWebRequest比较复杂难用,而内置的WebClient先天不足。

.NET 4.5中新增了HttpClient,但可惜.NET4.0不支持XP,所以暂时只能放弃HttpClient了。在这种种背景之下,我花了很长的时间来打磨这个网络库。虽然起名叫Network,但是目前专注于HTTP库。

这个网络库在订票助手.NET中得到了广泛全面的使用,几乎所有对12306发出的请求都是由它发出的。在订票助手.NET中,最近四个月中,由它发出的请求过亿,其稳定性也是蛮有保证的嘛。

1.功能特点&运行需求

其实它是对HttpWebRequest/HttpWebResponse的包装,目的是为了用起来更简单明了。设计的时候就为了提供更高的可用性和扩展性。所以……它具备……如下的特性。

  • 高综合处理能力:自动处理Cookies,自动跟踪引用页,自动GZIP压缩解压缩,自动编码识别……
  • 自动的数据处理能力:理论上你想发的数据,不用转换丢给它,它都能给你发出去;理论上你想收的对象,类型丢给它, 它都能给你弄回来……
  • 高健壮性:如果不是特殊情况,坚决不抛异常让你去catch。相反的是,它用状态来向你表示结果是否正确
  • 高处理能力:完全多线程处理,支持同步、异步、任务模式,异步时甚至能自动处理同步线程上下文,想用.NET中的await?没问题
  • 高扩展性:丰富的事件以及扩展性支持,你可以继承它来实现自己想做的事情。甚至都自带了抓包。。。。

由于编写时使用了大量的匿名类型和表达式,因此不能用于.NET3.5以下的平台。目前支持的平台为.NET3.5/4/4.5。其中,运行在3.5平台上时,个别特性无法使用。

2.先来看几个例子吧

口说无凭,先来看几个栗子吧。

提示

为了代码编写方便,以下全用.NET中的异步模式来编写(async/await),同步和异步的代码在后续的教程中提供。

此处仅为展示基本的用法,更详细的使用说明和实例将会在后续提供。

2.1 先来瞄一下我们的测试程序界面和测试网页

这里准备了一个简单的测试程序来展示库的基本用法。所以呢,先来个网页用来返回数据吧。

这里准备的服务器端程序非常简单,就是一个普通的aspx页面,接收一个GET或POST请求,将表单中所有数据、当前地址、是否是JSONP请求以及上传的文件信息返回。值得一提的是,如果上传了文件,返回的文件数据是经过base64编码的结果。

代码如下。

protected async void Page_Load(object sender, EventArgs e)
{
	var callback = Request.QueryString["callback"];	//是否是JSONP请求
	var isJsonP = !string.IsNullOrEmpty(callback);

	Response.ContentType = isJsonP ? "application/javascript" : "application/json";	//根据是否是JSONP设置正确的响应类型
	if (isJsonP)
	{
		Response.Write(callback);
		Response.Write("(");
	}
	//form data
	var form = new Dictionary<string, string>();
	foreach (var key in Request.Form.AllKeys)
	{
		form.Add(key, Request.Form[key]);
	}

	//filedata
	string filedata = null;
	string filename = null;
	var filelength = 0;
	if (Request.Files.Count > 0)
	{
		filename = Request.Files[0].FileName;
		filelength = Request.Files[0].ContentLength;

		var buffer = new byte[filelength];
		filelength = await Request.Files[0].InputStream.ReadAsync(buffer, 0, buffer.Length);
		filedata = Convert.ToBase64String(buffer, 0, filelength);
	}
	//返回JSON结果
	Response.Write(JsonConvert.SerializeObject(new
	{
		ret = true,	//始终为true
		url = Request.RawUrl,	//原始地址
		jsonp = isJsonP,	//是否是jsonp
		form,	//表单数据
		file = new	//文件信息
		{
			name = filename,
			length = filelength,
			data = filedata
		}
	}));

	if (isJsonP)
	{
		Response.Write(");");
	}
}

而下面这是测试程度界面。代码后面详述。

fslib_network_demo_1

注意红框的地址,这里是本地的测试服务器地址。

2.2 最简单的GET请求:抓百度首页

最常见的GET请求一个网页。测试代码如下。

点击“抓百度首页”按钮后的响应代码。

private async void btnGrabBdPage_Click(object sender, EventArgs e)
{
	InitWorkingUI();
 	AppendText("正在请求 http://www.baidu.com/ ...");
 
	var client = new HttpClient();
	var context = client.Create<string>(HttpMethod.Get"http://www.baidu.com/");
	await context.SendTask();
 
	if (context.IsValid())
	{
		AppendText(context.Result);
	}
	else
	{
		AppendText("错误!状态码:" + context.Response.Status);
		AppendText("服务器响应:" + context.ResponseContent);
	}
	WorkingFinished();
}

上面的示例,真正核心的部分从 var client=if(context.IsValid()) 判断语句结束时结束。流程非常简单,新建个ClientCreate一个请求上下文context),发送并等待判断是否成功IsValid()),显示结果。最终结果如下。

fslib_network_demo_2

是不是很简单呢?嗯。不过GET请求过于简单,用其它方法写起来也不见得会麻烦多少。所以继续吧。

注意上面用到了一些辅助函数,这些函数在下面都用到了,以下贴出来。

辅助函数

#region 辅助函数
 
void InitWorkingUI()
{
	txtResult.Clear();
	pgWaiting.Visible = true;
}
 
void AppendText(string txt)
{
	txtResult.AppendText(txt);
	txtResult.AppendText(Environment.NewLine);
	txtResult.AppendText(Environment.NewLine);
	txtResult.ScrollToCaret();
}
 
void WorkingFinished()
{
	pgWaiting.Visible = false;
}
 
#endregion

2.3 最简单的数据处理请求:抓一个图片

OK,现在来抓个百度的图片玩吧。这种情况下代码是不是比上一个例子复杂呢?看代码吧。

Snippet

private async void btnGrabBdLogo_Click(object sender, EventArgs e)
{
	InitWorkingUI();
 
 
	AppendText("正在请求 http://www.baidu.com/img/bdlogo.png ...");
 
	var client = new HttpClient();
	var context = client.Create<Image>(HttpMethod.Get"http://www.baidu.com/img/bdlogo.png");
	await context.SendTask();
 
	if (context.IsValid())
	{
		AppendText("正在显示图片...");
 
		var form = new Form() { Size = context.Result.Size };
		var pic = new PictureBox();
		form.Controls.Add(pic);
		pic.Dock = DockStyle.Fill;
		pic.Image = context.Result;
		form.Show();
		form.Activate();
	}
	else
	{
		AppendText("错误!状态码:" + context.Response.Status);
		AppendText("服务器响应:" + context.ResponseContent);
	}
	WorkingFinished();
 }

和上一个例子比较,差别很小。区别最大的是 Create 方法的类型参数从 String 变成了 Image (注意哦,不是显示图片。。)。对。你只要传入预期的对象类型,库就会自动帮你转换成目标的对象类型。所以结果如下。

fslib_network_demo_3

2.4 最简单的POST请求:POST一个字符串

嗯。POST数据这种事儿咱也不会少干。

先来个例子吧,咱做的最多的是把一个表单直接拼成字符串发出去。

private async void btnPostString_Click(object sender, EventArgs e)
{
	InitWorkingUI();
	var url = txtUrl.Text;
 
	AppendText(string.Format("正在请求 {0} ...", url));
 
	var client = new HttpClient();
	var context = client.Create<JsonContent>(HttpMethod.Post, url, data: "a=1&b=2&c=520");
	await context.SendTask();
 
	if (context.IsValid())
	{
		AppendText("成功..."); 
		DumpObject(context.Result);
	}
	else
	{
		AppendText("错误!状态码:" + context.Response.Status);
		AppendText("服务器响应:" + context.ResponseContent);
	}
	WorkingFinished();
}
 
void DumpObject(JsonContent obj)
{
	AppendText("返回:" + obj.Ret);
	AppendText("JSONP:" + obj.JsonP);
	AppendText("请求地址:" + obj.Url);
	AppendText("表单数据");
	AppendText("-----------------");
	AppendText(string.Join(Environment.NewLine, obj.Form.Select(s => s.Key + "\t==>\t" + s.Value)));
	AppendText("");
	AppendText("文件数据");
	AppendText("-----------------");
	if (obj.File == null || string.IsNullOrEmpty(obj.File.Name))
	{
		AppendText("没有文件");
	}
	else
	{
		AppendText("文件名\t==>\t" + obj.File.Name);
		AppendText("文件大小\t==>\t" + obj.File.Length.ToSizeDescription());
		AppendText("文件内容\t==>\t" + obj.File.Data);
	}
 
}

上面的主要代码没变,区别在于加了一个DumpObject方法来显示对象的内容。

注意加粗加下划线的那行代码。那是关键的一行区别,它定义了请求是POST,并且会发一个字符串做数据。这个例子的结果如下。

fslib_network_demo_4

 

备注一下,那个JsonContent是个对象,声明如下。

public class JsonContent
{
	public bool Ret { getset}
 
	public Dictionary<stringstringForm { getset}
 
	public JsonFileInfo File { getset}
 
	public bool JsonP { getset}
 
	public string Url { getset}
}
 
public class JsonFileInfo
{
	public string Name { getset}
 
	public int Length { getset}
 
	public string Data { getset}
}

 

2.5 来个高级点儿的POST请求:POST一个对象

直接POST字符串太奥特拉。我要直接POST一个对象,你信不信?

private async void btnPostObject_Click(object sender, EventArgs e)
{
	InitWorkingUI();
	var url = txtUrl.Text;
 
	AppendText(string.Format("正在请求 {0} ...", url));
 
	var client = new HttpClient();
	var context = client.Create<JsonContent>(HttpMethod.Post, url, data: new
	{
		a = 1,
		b = 2,
		c = 520,
		d = "you'r 2b."
	});
	await context.SendTask();
 
	if (context.IsValid())
	{
		AppendText("成功..."); 
		DumpObject(context.Result);
	}
	else
	{
		AppendText("错误!状态码:" + context.Response.Status);
		AppendText("服务器响应:" + context.ResponseContent);
	}
	WorkingFinished();
}

依然注意Create那行,注意看到data原来可以直接传递一个匿名对象进去的。其实实体对象也可以的啦。结果有差别吗?

fslib_network_demo_5

嗯。So Easy。

2.6 甚至……要发送数据但是是GET

有时候要GET请求,但是有参数。难道这种情况下我们就只能手动拼URL了么?非也……

private async void btnGetSendData_Click(object sender, EventArgs e)
{
	InitWorkingUI();
	var url = txtUrl.Text;
 
	AppendText(string.Format("正在请求 {0} ...", url));
 
	var client = new HttpClient();
	var context = client.Create<JsonContent>(HttpMethod.Get, url, data: new { a = 1, b = 2, c = 520, d = "you're 2b" });
	await context.SendTask();
 
	if (context.IsValid())
	{
		AppendText("成功...");
		DumpObject(context.Result);
	}
	else
	{
		AppendText("错误!状态码:" + context.Response.Status);
		AppendText("服务器响应:" + context.ResponseContent);
	}
	WorkingFinished();
}

以上代码,除了将Post改成Get外,和之前的请求并没有差别。但是,结果完全正确……

fslib_network_demo_10

注意看请求地址……

2.7 哪怕对方是个JSONP?不在话下

有时候我们要调用一个API,但是那个API是JSONP请求,也就是说返回的是一个javascript。这个搞不定吗?在大部分情况下,可以搞定……

private async void btnJsonP_Click(object sender, EventArgs e)
{
	InitWorkingUI();
	var url = txtUrl.Text + "?callback=_jsonCallback";
 
	AppendText(string.Format("正在请求 {0} ...", url));
 
	var client = new HttpClient();
	var context = client.Create<JsonContent>(HttpMethod.Get, url, data: "a=1&b=2&c=520");
	await context.SendTask();
 
	if (context.IsValid())
	{
		AppendText("成功...");
		AppendText("JSONP参数\t==>\t" + (context.AcquireResponseToObject().JsonpCallbackName ?? ""));
		DumpObject(context.Result);
	}
	else
	{
		AppendText("错误!状态码:" + context.Response.Status);
		AppendText("服务器响应:" + context.ResponseContent);
	}
	WorkingFinished();
}

以上代码的差别主要是URL地址里面加了JSONP回调地址。其它的并没有什么差别。但是……依然很OK的,啊哈哈哈。

fslib_network_demo_8

 注意看输出,不仅获得了结果,还获得了JsonP参数。

2.7 要上传文件?不是问题

最简单的上传任务,让用户任意选一个文件,然后post到服务器上去。

private async void btnUpFile_Click(object sender, EventArgs e)
{
	MessageBox.Show(this"为了避免太慢,请选择小文件。");
	var ofd = new OpenFileDialog();
	ofd.Filter = "所有文件(*.*)|*.*";
	if (ofd.ShowDialog() != DialogResult.OK)
		return;
 
	InitWorkingUI();
	var url = txtUrl.Text;
 
	AppendText(string.Format("正在请求 {0} ...", url));
 
	var client = new HttpClient();
	var context = client.Create<JsonContent>(HttpMethod.Post, url, data: new { a = 1, b = 2, c = 520, d = "you're 2b"file = new HttpPostFile("file", ofd.FileName) });
	await context.SendTask();
 
	if (context.IsValid())
	{
		AppendText("成功...");
		DumpObject(context.Result);
	}
	else
	{
		AppendText("错误!状态码:" + context.Response.Status);
		AppendText("服务器响应:" + context.ResponseContent);
	}
	WorkingFinished();
}

有没有感觉上传文件都这么简单?嗯。。。

fslib_network_demo_7

2.9 服务器出错了?

在传统的请求里面,一般出错后都是异常,要你try来catch去,十分痛苦不说,你还不知道到底是啥错。

所以这里专门针对错误做了处理,哪怕错误都让你知道为啥……

private async void btnGrab404_Click(object sender, EventArgs e)
{
	InitWorkingUI();
 
 
	AppendText("正在请求 http://www.fishlee.net/404.html ...");
 
	var client = new HttpClient();
	var context = client.Create<string>(HttpMethod.Get"http://www.fishlee.net/404.html");
	await context.SendTask();
 
	if (!context.IsValid())
	{
		AppendText("错误!状态码:" + context.Response.Status);
		AppendText("服务器响应:" + context.ResponseContent);
	}
	else
	{
		throw new Exception("不应该执行到这里!");
	}
	WorkingFinished();
}

你看……错误原因一目了然,服务器错误的信息也告诉你了。

fslib_network_demo_9

3. 引用&文档

嗯好啦,看到这里,你是不是也想试试了?嗯好吧。

目前发布的版本仅可以使用Nuget安装,如下所示。

fslib_network_demo_install

4. 补充说明

  • 此网络库依赖 FSLib.Extension 库(没错,我之前发的扩展库。。)以及 Newtonsoft.Json库(也就是大名鼎鼎的Json.NET)库
  • 此网络库目前不开源,禁止用于商业目的
  • 后续会有更详细的教程以及实例应用
  • 如果您发现了问题或有任何建议,欢迎在论坛提出

5. 相关网址

喜欢 (26)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(69)个小伙伴在吐槽
  1. 老铁,这个库支持HTTP摘要认证吗?

    fgre2019-08-24 06:14 回复
  2. 老板 怎么设置全局user-agant

    鱼粉2016-08-06 08:50 回复
    • HttpSetting对象有一个DefaultUserAgent

      木魚2016-08-08 03:01 回复
      • 无效 还是以iFish_Network_Client作为User-Agant发请求

        鱼粉2016-08-11 17:07 回复
        • AppendLibAuthorVendor=false;

          木魚2016-08-12 00:28 回复
  3. 最新的2.0版本DLL 运行第一个小例子报错,这句话报错:await context.SendTask();
    错误 1 “FSLib.Network.Http.HttpContext”不包含“SendTask”的定义,并且找不到可接受类型为“FSLib.Network.Http.HttpContext”的第一个参数的扩展方法“SendTask”(是否缺少 using 指令或程序集引用?) F:\My Demos\Network_Test\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs 28 27 WindowsFormsApplication1

    wjw2016-06-01 23:52 回复
    • .NET版本是4.0+吗?

      木魚2016-06-03 18:10 回复
      • 怎么改了user-agant没用啊

        鱼粉2016-07-08 10:55 回复
        • Setting 里面改。

          木魚2016-07-11 11:13 回复
          • 改了没用怎么办 只有在context里改有用 外面改没用。 能不能这个Header和代理加到HttpClient的全局。会方便很多。

            鱼粉2016-07-15 10:42
    • 2.0 哪里发布的

      鱼粉2016-07-08 10:54 回复
    • 啥意思?去这里提问吧 http://ask.fishlee.net/explore/category-21

      木魚2016-07-15 15:35 回复
  4. 请问服务返回的响应时间怎么精确到毫秒

    fishfan2016-04-25 11:54 回复
    • 。。请问您说的是什么响应时间?

      木魚2016-04-25 17:43 回复
      • 比如我发送了一个http请求,服务会给我响应. 我是想知道服务器发出响应时的服务器时间(毫秒或微妙级)以及我收到这个响应花了多少时间(毫秒或微妙级).

        fishfan2016-04-26 08:29 回复
        • HttpContext有个Performance属性,它是个性能对象,里面有相关的时间戳。参见 http://docs.fishlee.net/ifish/fslib.network/index.html#topic_000000000000018C_members–.html

          木魚2016-04-26 11:23 回复
          • 这些都是本机时间 我其实想获取服务器的时间 毫秒级的 有没有办法. 我现在拿的是context.Response.Date是秒级的. 很不精确.

            fishfan2016-04-26 16:33
        • 服务器时间?拿不到的,想其它辙吧。

          木魚2016-04-26 16:58 回复
          • 我就是调整本地时间和服务器时间分毫不差.哈哈.我再想想看.谢谢老板.

            fishfan2016-04-26 17:08
  5. 请教下,按照2.7 上传 提示 MethodNotAllowed 是为什么

    屈立亭2016-04-01 09:54 回复
    • 我知道了,是我服务器的问题 谢谢

      屈立亭2016-04-01 10:58 回复
  6. 记得初二的时候就关注了 你的博客 自己也想学C# 两年过去了 我还是没有一点进展…….现在准备 用你的这个库 学学POST。。。嘿嘿!!!!!!!!!

    小哲2016-03-24 23:58 回复
  7. 2.2 中 var context = client.Create(HttpMethod.Get, "http://www.baidu.com/"); 网址需替换为https,不替换的话会报错302 Found

    Francis2016-03-22 17:27 回复
    • 嗯,百度的http加密是最近的事情,写博客的时候没有这个。302不是错误其实,只是默认是不开启自动跳转的。

      木魚2016-03-22 19:02 回复
  8. 怎么设置Origin

    12015-12-22 10:51 回复
    • 最新版本有直接的属性可用。

      木魚2015-12-22 13:24 回复
  9. 怎么设置keep-alive

    12015-12-22 10:50 回复
  10. 如何自动处理cookies的能举个例子吗,比如需要用A网页的cookies,才能取到 B网页数据

    ACMilan2015-12-14 08:02 回复
    • 这个的意思是所有交互过程中的Cookies是自动处理的。。。不需要手动处理。你这问题不对头啊,直接去A网页请求不就好了吗。

      木魚2015-12-14 12:02 回复
  11. 未能加载文件或程序集“Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)

    MeeSii2015-11-13 00:30 回复
    • 嗯,库的版本依赖有问题。。乃把JSON库升级到7.0,或用BindingRedirect做个重定向就行了。依赖的版本号是7.0,但是manifest里写成了6.0,自动装的话,装的是6.0的库。

      木魚2015-11-17 11:55 回复
  12. 鱼大,如何上传一个 multipart/form-data 格式的二进制图片到网站?谢谢

    我都唔俾2015-10-22 17:19 回复
  13. 这个和微软的HttpClient比起来有什么优点呢, 要说4.0的话引了BCL和HttpClient也能支持的啊, 我看12306助手也引了BCL的啊

    逸风之狐2015-09-25 15:08 回复
    • 使用简单,功能足够。

      木魚2015-09-25 21:21 回复
  14. 大神你好;我用你的类库,出现一个问题;http://www.pbc.gov.cn/ 这个网站用你的类库怎么也打不开,老是提示“请开启JavaScript并刷新该页.”;这个怎么弄呢?还请不吝赐教,谢谢!

    孙权2015-08-17 11:50 回复
    • 用类库打开是啥意思?

      木魚2015-08-17 23:40 回复
    • 看了一下,那个应该是用了360安全宝做了拦截,需要在访问前执行一段js,目的应该是为了阻止非浏览器抓取。

      木魚2015-08-18 02:57 回复
      • 那执行那段代码呢?如何执行,请赐教,谢谢!

        孙权2015-08-18 09:20 回复
        • 那段js就在你看到的那个提示页面里,自己看下,就是设置了三个Cookeis

          木魚2015-08-18 10:08 回复
          • 实在不好意思,我都不好意思再问了,我看了半天,看不懂;我对这方面是基本文盲,如果你有时间还请帮我写个demo;谢谢啦,实在不好意思!:-)

            孙权2015-08-18 16:53
  15. 先试试再说

    阿水2015-05-26 12:37 回复
  16. 我要远程登录一个网站。那个网站是用.net拖控件搞的。页面是尽是视图状态的Hidden代码,这种要怎么操作?

    虫虫2015-03-10 07:33 回复
    • 这个可能需要具体分析。如果需要post原始的状态数据的话,可能需要获得原来页面中所有的隐藏字段了。

      木魚2015-03-10 23:07 回复
      • 哦就是需要先get一下,把隐藏字段拿 下来然后post的时候带上。。那种页面一般一个页面好几个button控件。我怎么确定我post的数据是post给哪个 button的事件呢?

        虫虫2015-03-10 23:10 回复
        • 一般post回去的时候点击的按钮是根据表单的字段区分的。具体抓个包就可以看到了。

          木魚2015-03-11 00:08 回复
  17. 鱼大就是厉害。

    Demo2015-01-31 23:25 回复
  18. “System.InvalidOperationException”类型的未经处理的异常在 FSLib.Network.dll 中发生

    其他信息: 对象的当前状态使该操作无效

    哥本哈根2015-01-24 08:05 回复
    • 原来是同步异步的问题,选择.Send(),不使用任务模式就OK了; 谢谢!

      哥本哈根2015-01-24 08:25 回复
  19. 嘿嘿支持了,太好了。比网上苏飞net的要高级一些。0028.gif 评论框框好可爱~~~

    Kvkens2015-01-21 22:23 回复
  20. 前辈,在上面的示例代码中,很关键的一点是对HttpClient类的使用,
    您的网络库是不是包含了提供了这个类的?我们要使用这个类只需要
    应用这个网络库就可以了?

    miaosha5s2015-01-20 13:36 回复
    • 这个网络库就是提供了这个类了啊。。。安装对应的包就有了的。

      木魚2015-01-20 13:37 回复
  21. 都是需要引用什么命名空间?我这里提示“未能找到类型或命名空间名称“HttpClient”(是否缺少 using 指令或程序集引用?) ”

    sunny222015-01-20 08:45 回复
  22. DEMO怎么没下载地址呢

    小小波2015-01-19 17:31 回复
    • DEMO很简单啊。。几乎所有源码都提供了

      木魚2015-01-19 20:52 回复
      • 还是想要个demo。楼主可能忽略了自己认为的基础部分,但是我等小白按照源码打上无法运行。

        sunny222015-01-20 09:06 回复
        • 后面会有实例项目的,DEMO只是演示。。。

          木魚2015-01-20 12:41 回复
  23. 84.gif要是能开源就好了

    空城2015-01-19 15:43 回复
    • 不开源是暂定,不排除后续开源的可能。 004.gif

      木魚2015-01-19 16:22 回复
      • 期待开源啊!

        cuibty2015-06-13 12:42 回复
  24. 请问, 这个库可以用来编写调用微信API的PC程序么?

    光芒万丈美少年2015-01-19 13:30 回复
    • 只要是HTTP的都可以。

      木魚2015-01-19 13:47 回复
  25. 我擦。。。虽然看不懂但我居然看完了。。。

    _Zane2015-01-19 11:59 回复
    • 038.gif

      木魚2015-01-19 12:19 回复
      • 鱼儿,我在VS搜不到你的插件呢!。

        汪灵2015-01-19 17:03 回复
        • 在项目引用节点,单击右键,选择nuget程序包,然后选择联机,包含预发行版,输入关键字,OK了;

          哥本哈根2015-01-24 07:47 回复
      • await context.SendTask();这个再NetWork的2.0里面不能用了吗?
        错误 1 “FSLib.Network.Http.HttpContext”不包含“SendTask”的定义,并且找不到可接受类型为“FSLib.Network.Http.HttpContext”的第一个参数的扩展方法“SendTask”(是否缺少 using 指令或程序集引用?) F:\My Demos\Network_Test\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs 28 27 WindowsFormsApplication1

        wjw2016-06-01 23:42 回复
        • SendTask() 方法已经改名为 SendAsync()

          木魚2016-06-07 10:06 回复