- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
做.NET应用开发肯定会用到网络通信,而进程间通信是客户端开发使用频率较高的场景.
进程间通信方式主要有命名管道、消息队列、共享内存、Socket通信,个人使用最多的是Sokcet相关.
而Socket也有很多使用方式,Socket、WebSocket、TcpClient、UdpClient,是不是很多?HttpClient与TcpClient、WebSocket之间有什么关系?这里我们分别介绍下这些通信及使用方式 。
Socket是传输通信协议么?No,Socket是一种传输层和应用层之间、用于实现网络通信的编程接口。Socket可以使用各种协议如TCP、UDP协议实现进程通信,TCP/UDP才是传输通信协议 。
Socket位于传输层与应用层之间,接口在System.Net.Sockets命名空间下。下面是Socket以TCP通信的DEMO:
//创建一个 Socket 实例 Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //连接到服务器 clientSocket.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8000)); //发送数据 string message = "Hello, Server!"; byte[] data = Encoding.ASCII.GetBytes(message); clientSocket.Send(data); //接收数据 byte[] buffer = new byte[1024]; int bytesRead = clientSocket.Receive(buffer); Debug.WriteLine(Encoding.ASCII.GetString(buffer, 0, bytesRead)); clientSocket.Close();
TCP/UDP均是位于传输层的通信协议,所以Socket的使用也是位于传输层的通信操作 。
TCP是面向连接,提供可靠、顺序的数据流传输。用于一对一的通信,即一个TCP连接只能有一个发送方和一个接收方。详细连接方式是,先通过三次握手建立连接、然后传输数据,传输数据完再通过4次挥手关闭连接。所以适用于需要数据完整性和可靠传输的场景 。
而UDP则是无连接的,不需要建立和维护连接状态,不提供确认机制,也不重传丢失的数据报,但也因此传输实时性高,适合低延时、数据量小、广播场景 。
基于Socket抽象编程接口,TCP、UDP构建更高级别抽象网络编程TcpClient、UdpClient,它们用于简化TCP网络编程中的常见任务 。
TcpClient、UdpClient是 .NET 提供的用于方便管理TCP和UDP网络通信的类,下面是对应的Demo 。
Tcp服务端:
1 using System; 2 using System.Net; 3 using System.Net.Sockets; 4 using System.Text; 5 6 class TcpServerExample 7 { 8 public static void Main() 9 { 10 TcpListener listener = new TcpListener(“127.0.0.1", 8000); 11 listener.Start(); 12 Console.WriteLine("Server is listening on port 8000..."); 13 14 TcpClient client = listener.AcceptTcpClient(); 15 NetworkStream stream = client.GetStream(); 16 17 byte[] data = new byte[1024]; 18 int bytesRead = stream.Read(data, 0, data.Length); 19 Console.WriteLine("Received: " + Encoding.ASCII.GetString(data, 0, bytesRead)); 20 21 byte[] response = Encoding.ASCII.GetBytes("Hello, Client!"); 22 stream.Write(response, 0, response.Length); 23 24 stream.Close(); 25 client.Close(); 26 listener.Stop(); 27 } 28 }
TCP客户端:
1 using System; 2 using System.Net.Sockets; 3 using System.Text; 4 5 class TcpClientExample 6 { 7 public static void Main() 8 { 9 TcpClient client = new TcpClient("127.0.0.1", 8000); 10 NetworkStream stream = client.GetStream(); 11 12 byte[] message = Encoding.ASCII.GetBytes("Hello, Server!"); 13 stream.Write(message, 0, message.Length); 14 15 byte[] data = new byte[1024]; 16 int bytesRead = stream.Read(data, 0, data.Length); 17 Debug.WriteLine("Received: " + Encoding.ASCII.GetString(data, 0, bytesRead)); 18 19 stream.Close(); 20 client.Close(); 21 } 22 }
Udp服务端:
1 using System; 2 using System.Net; 3 using System.Net.Sockets; 4 using System.Text; 5 6 class UdpServerExample 7 { 8 public static void Main() 9 { 10 UdpClient udpServer = new UdpClient(8000); 11 IPEndPoint remoteEP = new IPEndPoint(”127.0.0.1“, 0); 12 13 Console.WriteLine("Server is listening on port 8000..."); 14 15 byte[] data = udpServer.Receive(ref remoteEP); 16 Console.WriteLine("Received: " + Encoding.ASCII.GetString(data)); 17 18 byte[] response = Encoding.ASCII.GetBytes("Hello, Client!"); 19 udpServer.Send(response, response.Length, remoteEP); 20 21 udpServer.Close(); 22 } 23 }
Udp客户端:
1 using System; 2 using System.Net; 3 using System.Net.Sockets; 4 using System.Text; 5 6 class UdpClientExample 7 { 8 public static void Main() 9 { 10 UdpClient udpClient = new UdpClient(); 11 IPEndPoint remoteEP = new IPEndPoint(”127.0.0.1", 8000); 12 13 byte[] message = Encoding.ASCII.GetBytes("Hello, Server!"); 14 udpClient.Send(message, message.Length, remoteEP); 15 16 byte[] data = udpClient.Receive(ref remoteEP); 17 Console.WriteLine("Received: " + Encoding.ASCII.GetString(data)); 18 19 udpClient.Close(); 20 } 21 }
上面是基本的网络通信DEMO,TcpClient用于基于连接、可靠的TCP通信,适用于需要数据完整性和可靠传输的场景。Udp用于无连接、不保证传输的UDP通信,适用于对实时性要求高、允许少量数据丢失的场景(如视频流)。会议场景下的传屏软件适合用这个协议,传屏发送端固定帧率一直推送,网络丢失几帧问题不大,重要的是延时低了很多.
TcpClient、UdpClient是位于传输层的通信类,分别实现了基于TCP和UDP协议的通信功能.
HttpClient 。
讲完传输层的网络通信类,就要说下应用层的HttpClient,这是专门用于HTTP协议的通信 。
Http与TCP/UDP均是网络通信协议,TCP、UDP位于传输层,HTTP传于应用层,而且HTTP是基于TCP面向连接的。TCPHTTP1.1之后引入持久连接,允许一个TCP连接进行多次请求/响应传输。HTTP层相比TCP它关注请求、响应的内容 。
HttpClient是Http协议的通信类,提供了封装好的、高级的HTTP功能(如发起GET, POST请求,处理响应等).
HttpClient可以用于Web接口如Restful API的调用,我这边Windows应用的WebApi基础组件库就是用HttpClient实现的.
HttpClient类,在System.Net.Http.HttpClient命名空间下,HttpClient的内部实现是基于Socket的。也就是说,HttpClient底层使用Socket接口来建立连接并传输数据,但它隐藏了这些细节,为开发者提供了一个更简洁的API.
下面是我基于HttpClient实现的Web服务各类操作入口代码,可以简单浏览下:
1 /// <summary> 2 /// 请求/推送数据 3 /// </summary> 4 /// <typeparam name="TResponse"></typeparam> 5 /// <param name="request"></param> 6 /// <returns></returns> 7 public async Task<TResponse> RequestAsync<TResponse>(HttpRequest request) where TResponse : HttpResponse, new() 8 { 9 var requestUrl = request.GetRequestUrl(); 10 try 11 { 12 using var client = CreateHttpClient(request); 13 var requestMethod = request.GetRequestMethod(); 14 switch (requestMethod) 15 { 16 case RequestMethod.Get: 17 { 18 using var response = await client.GetAsync(requestUrl); 19 return await response.GetTResponseAsync<TResponse>(); 20 } 21 case RequestMethod.Post: 22 { 23 using var httpContent = request.GetHttpContent(); 24 using var response = await client.PostAsync(requestUrl, httpContent); 25 return await response.GetTResponseAsync<TResponse>(); 26 } 27 case RequestMethod.Put: 28 { 29 using var httpContent = request.GetHttpContent(); 30 using var response = await client.PutAsync(requestUrl, httpContent); 31 return await response.GetTResponseAsync<TResponse>(); 32 } 33 case RequestMethod.Delete: 34 { 35 using var response = await client.DeleteAsync(requestUrl); 36 return await response.GetTResponseAsync<TResponse>(); 37 } 38 case RequestMethod.PostForm: 39 { 40 using var requestMessage = new HttpRequestMessage(HttpMethod.Post, requestUrl); 41 using var httpContent = request.GetHttpContent(); 42 requestMessage.Content = httpContent; 43 using var response = await client.SendAsync(requestMessage); 44 return await response.GetTResponseAsync<TResponse>(); 45 } 46 } 47 return new TResponse() { Message = $"不支持的请求类型:{requestMethod}" }; 48 } 49 catch (ArgumentNullException e) 50 { 51 return new TResponse() { Code = NetErrorCodes.ParameterError, Message = e.Message, JsonData = e.StackTrace }; 52 } 53 catch (TimeoutException e) 54 { 55 return new TResponse() { Code = NetErrorCodes.TimeOut, Message = e.Message, JsonData = e.StackTrace }; 56 } 57 catch (Exception e) 58 { 59 return new TResponse() { Message = e.Message, JsonData = e.StackTrace }; 60 } 61 }
HttpClient封装后的网络基础组件调用方式,也比较简单.
添加接口请求说明,参数及请求参数均统一在一个类文件里定义好:
1 /// <summary> 2 /// 内网穿透注册接口 3 /// </summary> 4 [Request("http://frp.supporter.ws.h3c.com/user/register",RequestMethod.Post)] 5 [DataContract] 6 internal class RegisterFrpRequest : HttpRequest 7 { 8 public RegisterFrpRequest(string sn, string appName) 9 { 10 Sn = sn; 11 SeverNames = new List<RequestServiceName>() 12 { 13 new RequestServiceName(appName,"http") 14 }; 15 } 16 [DataMember(Name = "sn")] 17 public string Sn { get; set; } 18 19 [DataMember(Name = "localServerNames")] 20 public List<RequestServiceName> SeverNames { get; set; } 21 }
再定义请求结果返回数据,基类HttpResponse内有定义基本参数,状态Success、状态码Code、返回描述信息Message:
1 [DataContract] 2 class RegisterFrpResponse : HttpResponse 3 { 4 5 [DataMember(Name = "correlationId")] 6 public string CorrelationId { get; set; } 7 8 [DataMember(Name = "data")] 9 public FrpRegisterData Data { get; set; } 10 11 /// <summary> 12 /// 是否成功 13 /// </summary> 14 public bool IsSuccess => Success && Code == 200000 && Data != null; 15 }
然后,业务层可以进行简洁、高效率的调用:
var netClient = new NetHttpClient();
var response = await netClient.RequestAsync<RegisterFrpResponse>(new RegisterFrpRequest(sn, appName));
WebSocket也是一个应用层通信,不同于可以实现俩类协议TCP/UDP的Socket,WebSocket只依赖于HTTP/HTTPS连接.
一旦握手成功,客户端和服务器之间可以进行双向数据传输,可以传输字节数据也可以传输文本内容.
持久连接:WebSocket 是持久化连接,除非主动关闭,否则在整个会话期间连接保持开放.
全双工通信:客户端和服务器可以随时发送数据,通信不再是单向的。使用System.Net.WebSockets.ClientWebSocket类来实现WebSocket通信,通过减少 HTTP 请求/响应的开销、延时较低.
而WebSocket与HttpClient之间呢,都用于应用层的网络通信,但它们的用途和通信协议是不同的.
HttpClient使用 HTTP 协议,WebSocket 使用 WebSocket 协议,该协议在初始连接时通过 HTTP/HTTPS握手,然后转换为基于TCP通信的WebSocket协议。所以虽然都有使用HTTP协议,但WebSocket后续就切换至基于TCP的全双工通信了 。
HttpClient基于请求/响应模式,每次通信由客户端向服务器发起请求。WebSocket提供全双工通信,客户端和服务器都可以主动发送数据.
HttpClient主要用于访问 RESTful API、下载文件或者发送HTTP请求。WebSocket主要用于实现低延迟的实时通信,如进程间通信、局域网通信等.
我团队Windows应用所使用的进程间通信,就是基于WebSocketSharp封装的。WebSocketSharp是一个功能全面、易于使用的第三方 WebSocket 库 GitHub - sta/websocket-sharp 。
至于为啥不直接使用ClientWebSocket。。。是因为当时团队还未切换.NET,使用的是.NETFramework.
后面团队使用的局域网通信基础组件就是用ClientWebSocket了.
下面是我封装的部分WebSocket通信代码,事件发送(广播)、以及监听其它客户端发送过来的事件消息:
1 /// <summary> 2 /// 发送消息 3 /// </summary> 4 /// <typeparam name="TInput">发送参数类型</typeparam> 5 /// <param name="client">目标客户端</param> 6 /// <param name="innerEvent">事件名</param> 7 /// <param name="data">发送参数</param> 8 /// <returns></returns> 9 public async Task<ClientResponse> SendAsync<TInput>(string client, InnerEventItem innerEvent, TInput data) 10 { 11 var message = new ChannelSendingMessage(client, new ClientEvent(innerEvent.EventName, innerEvent.EventId, true), _sourceClient); 12 message.SetData<TInput>(data); 13 return await SendMessageAsync(ChannelMessageType.ClientCommunication, message); 14 } 15 16 /// <summary> 17 /// 订阅消息 18 /// </summary> 19 /// <param name="client">目标客户端</param> 20 /// <param name="innerEvent">事件名称</param> 21 /// <param name="func">委托</param> 22 public ClientSubscribedEvent SubscribeFunc(string client, InnerEventItem innerEvent, Func<ClientResponse, object> func) 23 { 24 var eventName = innerEvent?.EventName; 25 if (string.IsNullOrEmpty(eventName) || func == null) 26 { 27 throw new ArgumentNullException($"{nameof(eventName)}或{nameof(func)},参数不能为空!"); 28 } 29 30 var subscribedEvent = new ClientSubscribedEvent(client, innerEvent, func); 31 SubscribeEvent(subscribedEvent); 32 return subscribedEvent; 33 } 34 35 /// <summary> 36 /// 订阅消息 37 /// </summary> 38 /// <param name="client">目标客户端</param> 39 /// <param name="innerEvent">事件名称</param> 40 /// <param name="func">委托</param> 41 public ClientSubscribedEvent SubscribeFuncTask(string client, InnerEventItem innerEvent, Func<ClientResponse, Task<object>> func) 42 { 43 var eventName = innerEvent?.EventName; 44 if (string.IsNullOrEmpty(eventName) || func == null) 45 { 46 throw new ArgumentNullException($"{nameof(eventName)}或{nameof(func)},参数不能为空!"); 47 } 48 49 var subscribedEvent = new ClientSubscribedEvent(client, innerEvent, func); 50 SubscribeEvent(subscribedEvent); 51 return subscribedEvent; 52 }
。
关键词:TCP/UDP,HTTP,Socket,TcpClient/UdpClient,HttpClient,WebSocket 。
最后此篇关于.NETTCP、UDP、Socket、WebSocket的文章就讲到这里了,如果你想了解更多关于.NETTCP、UDP、Socket、WebSocket的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
背景: 我有一个在带有NetTCP绑定(bind)的Windows服务中托管WCF服务的系统。要将新服务添加到集合中,您只需在 services/>中添加标准WCF配置条目,然后在自定义配置部分中添加
我有一个带有 HTTP 绑定(bind)的 WCF 服务,它返回 500k 大小的数据集。使用 WCF 默认日志记录时,我可以看到消息和随每条消息传输的数据
做.NET应用开发肯定会用到网络通信,而进程间通信是客户端开发使用频率较高的场景。 进程间通信方式主要有命名管道、消息队列、共享内存、Socket通信,个人使用最多的是Sokcet相关。 而Soc
我有一个使用 nettcpBinding(框架 4.0)的 WCF 服务和客户端。客户端请求图像,服务器查找该图像并通过回调将其发送回客户端。 WCF 服务托管在 Windows 窗体应用程序中。我让
我们在为 IIS 本地托管的 WCF Web 服务配置 netTcp 时遇到问题。这是在带有 DotNet 4.0 (VS2012) 的 Windows 7 和 IIS 7 上,防火墙被禁用。 我们已
我在从客户端向 WCF net.tcp 服务发送大型 xml 时遇到问题,当调用该方法时,某些机器上的客户端会抛出内存不足异常,我无法在本地机器上重现该异常:异常消息:无法分配 33554432 字节
我正在尝试在同一网络上的多台计算机和一台服务器之间实现一些跨进程通信。我现在正在尝试的是将 WCF 与 NetTcpBinding 一起使用,托管在我在同一台机器上运行的应用程序中,但是当我尝试从另一
在尝试在 Mono 中构建客户端-服务器 WCF 应用程序时,我们遇到了一些问题。 将其简化为一个简单的示例,我们发现该服务一次仅接受一个客户端。如果另一个客户端尝试连接,它会挂起,直到第一个客户端断
我是 WCF 新手,我正在制作服务器/客户端应用程序,其中我需要一些用户/密码架构来维护每个客户端的一些自定义设置并记录谁访问该服务,但“安全”在由于信息不敏感,因此实际上并不需要通过网络的流量。因此
我有个问题。我想提供一系列使用 WCF 制作的服务。使用服务的客户端也是带有 WCF 的 .NET。我想要高速访问、快速响应、传输中小型数据契约(Contract)(主要的 .net 基本数据类型)。
我有一个没有互操作性要求的自定义 Intranet 应用程序。我们以编程方式在双工模式下构造一个 NetTcp channel 来传递消息。我们想更改消息编码,但无法弄清楚如何实现。 我们采用的方法(
我在 WCF 服务配置文件中定义了两个基地址:
所以我意识到这是一个相当沉重的问题,但这就是我想要衡量的。 我有一个服务器,它通过 WCF 接受可靠 session tcp 连接并打开到客户端的回调 channel 。 99.999%的时间,它只是
我正在编写一个 WCF 服务,需要模拟和 session 。 当我试图在我的本地机器上调用它时没问题,但在远程机器上它总是失败并出现这样的错误: Security Support Provider I
在成功让 WCF 服务和客户端使用 Http 相互通信后,我现在正尝试将其切换到 netTcp,以便我可以加密通信。但是,我无法根据该协议(protocol)建立连接。 更改服务上的 App.conf
我正在使用 WCF(使用回调契约(Contract))和 netTcpBinding 创建一个聊天应用程序。 我将该服务托管为 Windows 服务并从其他计算机访问它 通过客户端应用程序。 我现在面
我们的服务器是基于 WCF 的,它由 IIS 托管。我们使用 nettcp 作为我们的绑定(bind)。该应用程序正在运行,但我们仍然不清楚一件事:由于我们没有在配置中指定端口号,WCF/IIS 使用
我正在寻找最大值。与 netTcpBinding 一起使用的绑定(bind)的属性 maxConnections 的限制? 最佳答案 简单: Int32.MaxValue =2,147,483,64
首先,抱歉,我不流利。 我想弄清楚为什么当我们的环境具有高调用/秒率时我的 WCF 服务停止工作。我不确定仅仅增加超时时间就能解决问题。 我们有 2 个网络服务: 第一个托管在 IIS 7.5、Win
我有一个 WCF 服务。它有多个客户端和三个端点。端点绑定(bind)是 nettcp、wsHttp 和 basicHttp。如果我尝试通过 php 内置的 SoapClient 类连接到它,如下所示
我是一名优秀的程序员,十分优秀!