c# udp 高并发
2010-04-19 17:43:00 qiuqingpo 阅读数 8784

C# UDP通信
Internet协议族中有支持无连接的传输协议,即UDP协议。UDP协议提供了一种方法来发送经过封装的IP数据报,而且不必建立连接就

可以发送这些IP数据报。
服务器端:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace UDPServer
{
    class Program
    {
        static void Main(string[] args)
        {
            int recv;
            byte[] data = new byte[1024];

            //构建TCP 服务器

            //得到本机IP,设置TCP端口号        
            IPEndPoint ipep = new IPEndPoint(IPAddress.Any , 8001);
            Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram , ProtocolType.Udp);

            //绑定网络地址
            newsock.Bind(ipep);

            Console.WriteLine("This is a Server, host name is {0}",Dns.GetHostName());

            //等待客户机连接
            Console.WriteLine("Waiting for a client");

            //得到客户机IP
            IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
            EndPoint Remote = (EndPoint)(sender);
            recv = newsock.ReceiveFrom(data, ref Remote);
            Console .WriteLine ("Message received from {0}: ", Remote.ToString ());
            Console .WriteLine (Encoding .ASCII .GetString (data ,0,recv ));

            //客户机连接成功后,发送欢迎信息
            string welcome = "Welcome ! ";

            //字符串与字节数组相互转换
            data  = Encoding .ASCII .GetBytes (welcome );

            //发送信息
            newsock .SendTo (data ,data.Length ,SocketFlags .None ,Remote );
            while (true )
            {
                data =new byte [1024];
                //发送接受信息
                recv =newsock.ReceiveFrom(data ,ref Remote);
                Console .WriteLine (Encoding .ASCII .GetString (data ,0,recv));
                newsock .SendTo (data ,recv ,SocketFlags .None ,Remote );
            }
        }

    }
}

客户端:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace UDPClient
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] data = new byte[1024];
            string input ,stringData;

            //构建TCP 服务器

            Console.WriteLine("This is a Client, host name is {0}", Dns.GetHostName());

            //设置服务IP,设置TCP端口号
            IPEndPoint ipep = new IPEndPoint(IPAddress .Parse ("127.0.0.1") , 8001);

            //定义网络类型,数据连接类型和网络协议UDP
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            string welcome = "Hello! ";
            data = Encoding.ASCII.GetBytes(welcome);
            server.SendTo(data, data.Length, SocketFlags.None, ipep);
            IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
            EndPoint Remote = (EndPoint)sender;

            data = new byte[1024];
            //对于不存在的IP地址,加入此行代码后,可以在指定时间内解除阻塞模式限制
            //server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 100);
            int recv = server.ReceiveFrom(data, ref Remote);
            Console.WriteLine("Message received from {0}: ", Remote.ToString());
            Console.WriteLine(Encoding .ASCII .GetString (data,0,recv));
            while (true)
            {
                input = Console .ReadLine ();
                if (input =="exit")
                    break ;
                server .SendTo (Encoding .ASCII .GetBytes (input ),Remote );
                data = new byte [1024];
                recv = server.ReceiveFrom(data, ref Remote);
                stringData = Encoding.ASCII.GetString(data, 0, recv);
                Console.WriteLine(stringData);
            }
            Console .WriteLine ("Stopping Client.");
            server .Close ();           
        }

    }
}

MSDN 实例
// This constructor arbitrarily assigns the local port number.
UdpClient udpClient = new UdpClient(11000);
    try{
         udpClient.Connect("www.contoso.com ", 11000);

         // Sends a message to the host to which you have connected.
         Byte[] sendBytes = Encoding.ASCII.GetBytes("Is anybody there?");
     
         udpClient.Send(sendBytes, sendBytes.Length);

         // Sends a message to a different host using optional hostname and port parameters.
         UdpClient udpClientB = new UdpClient();
         udpClientB.Send(sendBytes, sendBytes.Length, "AlternateHostMachineName", 11000);

         //IPEndPoint object will allow us to read datagrams sent from any source.
         IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);

         // Blocks until a message returns on this socket from a remote host.
         Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
         string returnData = Encoding.ASCII.GetString(receiveBytes);
  
         // Uses the IPEndPoint object to determine which of these two hosts responded.
         Console.WriteLine("This is the message you received " +
                                      returnData.ToString());
         Console.WriteLine("This message was sent from " +
                                     RemoteIpEndPoint.Address.ToString() +
                                     " on their port number " +
                                     RemoteIpEndPoint.Port.ToString());

          udpClient.Close();
          udpClientB.Close();
         
          } 
       catch (Exception e ) {
                  Console.WriteLine(e.ToString());
        }
 
Microsoft Visual Studio 2005/.NET Framework 2.0


同时提供下列产品的其他版本:
•.NET Framework 3.0
•Microsoft Visual Studio 2008/.NET Framework 3.5
.NET Framework 类库UdpClient 成员
提供用户数据报 (UDP) 网络服务。

下表列出了由 UdpClient 类型公开的成员。

  公共构造函数
  名称  说明 
   UdpClient  已重载。初始化 UdpClient 类的新实例。
  公共属性
(请参见 受保护的属性 )   名称  说明 
  Available  获取从网络接收的可读取的数据量。
   Client  获取或设置基础网络 Socket。
  DontFragment  获取或设置 Boolean 值,指定 UdpClient 是否允许对 Internet 协议 (IP) 数据报进行分段。
  EnableBroadcast  获取或设置 Boolean 值,指定 UdpClient 是否可以发送或接收广播数据包。
  ExclusiveAddressUse  获取或设置 Boolean 值,指定 UdpClient 是否只允许一个客户端使用端口。
  MulticastLoopback  获取或设置 Boolean 值,指定是否将输出多路广播数据包传递给发送应用程序。
  Ttl  获取或设置一个值,指定由 UdpClient 发送的 Internet 协议 (IP) 数据包的生存时间 (TTL)。
  受保护的属性
  名称  说明 
   Active  获取或设置一个值,该值指示是否已建立默认远程主机。
  公共方法
(请参见 受保护的方法 )   名称  说明 
  BeginReceive  从远程主机异步接收数据报。 
  BeginSend  已重载。 将数据报异步发送到远程主机。 
   Close  关闭 UDP 连接。 
   Connect  已重载。 建立默认远程主机。 
   DropMulticastGroup  已重载。 退出多路广播组。 
  EndReceive  结束挂起的异步接收。 
  EndSend  结束挂起的异步发送。 
   Equals   已重载。 确定两个 Object 实例是否相等。 (从 Object 继承。)
   GetHashCode   用作特定类型的哈希函数。GetHashCode 适合在哈希算法和数据结构(如哈希表)中使用。 (从 Object 继承。)
   GetType   获取当前实例的 Type。 (从 Object 继承。)
   JoinMulticastGroup  已重载。 将 UdpClient 添加到多路广播组。 
   Receive  返回已由远程主机发送的 UDP 数据报。 
    ReferenceEquals   确定指定的 Object 实例是否是相同的实例。 (从 Object 继承。)
   Send  已重载。 将 UDP 数据报发送到远程主机。 
   ToString   返回表示当前 Object 的 String。 (从 Object 继承。)
  受保护的方法
  名称  说明 
  Dispose  释放由 UdpClient 占用的非托管资源,还可以另外再释放托管资源。 
   Finalize   允许 Object 在“垃圾回收”回收 Object 之前尝试释放资源并执行其他清理操作。 (从 Object 继承。)
   MemberwiseClone   创建当前 Object 的浅表副本。 (从 Object 继承。)
  显式接口实现
  名称  说明 
    System.IDisposable.Dispose  释放由 UdpClient 使用的所有资源。 

2019-04-24 11:12:44 qq_21703215 阅读数 445

转载自1:https://www.cnblogs.com/atree/p/Concurrency_Async.html
转载自2:https://blog.csdn.net/mss359681091/article/details/52056105

一 C#编程高并发的几种处理方法

并发(英文Concurrency),其实是一个很泛的概念,字面意思就是“同时做多件事”,不过方式有所不同。在.NET的世界里面,处理高并发大致有以下几种方法:

1,异步编程

异步编程就是使用future模式(又称promise)或者回调机制来实现(Non-blocking on waiting)。如果使用回调或事件来实现(容易callback hell),不仅编写这样的代码不直观,很快就容易把代码搞得一团糟。

不过在.NET 4.5 及以上框架中引入的async/await关键字(在.NET 4.0中通过添加Microsoft.Bcl.Async包也可以使用),让编写异步代码变得容易和优雅。通过使用async/await关键字,可以像写同步代码那样编写异步代码,所有的回调和事件处理都交给编译器和运行时帮你处理了,简单好用。

使用异步编程有两个好处:不阻塞主线程(比如UI线程),提高服务端应用的吞吐量。所以微软推荐ASP.NET中默认使用异步来处理请求。
例如:我用异步做微信模板消息推送。

/// <summary>
/// 使用异步Action测试异步模板消息接口
/// </summary>
/// <param name="checkcode"></param>
/// <returns></returns>
public async Task<string> TemplateMessageAsync(string openId, string first, string keyword1, string keyword2, string keyword3, string keyword4, string remark, string url)
{
    if (openId == null)
    {
        return ReturnString(7771, "OPENID不能为空");
    }
    else
    {
        var testData = new //TestTemplateData()
        {
            first = new TemplateDataItem(first),
            keyword1 = new TemplateDataItem(keyword1),
            keyword2 = new TemplateDataItem(keyword2),
            keyword3 = new TemplateDataItem(keyword3),
            keyword4 = new TemplateDataItem(keyword4),
            remark = new TemplateDataItem(remark)
        };

        var result = await TemplateApi.SendTemplateMessageAsync(_wechat.APPID, openId, "m6td4jp_heMA5rhopbUaHApOlp2DD5x18BMXWKj3M5U", url, testData);
        return ReturnString(0, "成功");
    }
}

2,并行编程

并行编程的出现实际上是随着CPU有多核而兴起的,目的是充分利用多核CPU的计算能力。并行编程由于会提高CPU的利用率,更适合客户端的一些应用,对于服务端的应用可能会造成负面影响(因为服务器本身就具有并行处理的特点,比如IIS会并行的处理多个请求)。我自己使用并行编程最多的场景是之前分析环境数据不确定度的时候,使用并行的方式计算蒙特卡洛模拟(计算上千次之后拟合),当然后来我使用泰勒级数展开来计算不确定度,没有这么多的计算量就无需并行了。当然在计算多方案结果比较的情况下,还是继续使用了并发计算。

在.NET中,并行的支持主要靠.NET 4.0引入的任务并行库和并行LINQ。通过这些库可以实现数据并行处理(处理方式相同,输入数据不同,比如我上面提到的应用场景)或者任务并行处理(处理方式不同,且数据隔离)。通过使用并行处理库,你不用关心Task的创建和管理(当然更不用说底层的线程了),只需要关注处理任务本身就行了。

具体的用法还是参考官方文档:https://msdn.microsoft.com/en-us/library/dd460693(v=vs.110).aspx

3,响应式编程

响应式编程最近成为了一个Buzzword,其实微软6年前就开始给.NET提供一个Reactive Extensions了。一开始要理解响应式编程有点困难,但是一旦理解了,你就会对它的强大功能爱不释手。简单来说,响应式编程把事件流看作数据流,不过数据流是从IEnumable中拉取的,而事件流是从IObservable推送给你的。为什么响应式编程可以实现并发呢?这是因为Rx做到线程不可知,每次事件触发,后续的处理会从线程池中任意取出一个线程来处理。且可以对事件设置窗口期和限流。举个例子,你可以用Rx来让搜索文本框进行延迟处理(而不用类似我很早的时候用个定时器来延迟了)。

要详细了解Rx最好的方式就是浏览 IntroToRx.com 这个网站,当然还有官方文档:https://msdn.microsoft.com/en-us/data/gg577609。

4,数据流编程

数据流(DataFlow)编程可能大家就更陌生了,不过还是有些常用场景可以使用数据流来解决。数据流其实是在任务并行库(TPL)上衍生出来的一套处理数据的扩展(也结合了异步的特性),TPL也是处理并行编程中任务并行和数据并行的基础库。

望文生义,TPL DataFlow就是对数据进行一连串处理,首先为这样的处理定义一套网格(mesh),网格中可以定义分叉(fork)、连接(join)、循环(loop)。数据流入这样的处理网格就能够并行的被处理。你可以认为网格是一种升级版的管道,实际上很多时候就是被当作管道来使用。使用场景可以是“分析文本文件中词频”,也可以是“处理生产者/消费者问题”。

参考资料当然也是官方文档:https://msdn.microsoft.com/en-us/library/hh228603(v=vs.110).aspx。

5,Actor模型

Scala有Akka,其实微软研究院也推出了Orleans来支持了Actor模型的实现,当然也有Akka.NET可用。Orleans设计的目标是为了方便程序员开发需要大规模扩展的云服务, 可用于实现DDD+EventSourcing/CQRS系统。

官方网站是:http://dotnet.github.io/orleans/

二 解决方案

最近几天一直在读代震军的博客,他是Discuz!NT的设计者,读了他的一系列关于Discuz!NT的架构设计文章,大呼过瘾,特别是Discuz!NT在解决高访问高并发时所设计的一系列方案,本人尤其感兴趣。写这篇文章的目的,算是对初次阅读之后的总结备忘吧,以便以后有时间亲自测试,如果能在生产环境中得到应用,那就更有参考价值了。

测试方法:
本地模拟测试网站高访问高并发采用的测试工具是大名鼎鼎的Loadrunner,这个工具做测试的一般都知道。在代震军的博客中,有以下几篇介绍了通过Loadrunner进行压力并发测试。

当DiscuzNT遇上了Loadrunner(上)
http://www.cnblogs.com/daizhj/archive/2009/09/25/1573926.html

当DiscuzNT遇上了Loadrunner(中)
http://www.cnblogs.com/daizhj/archive/2009/09/27/1574897.html

当DiscuzNT遇上了Loadrunner(下)
http://www.cnblogs.com/daizhj/archive/2009/09/27/1575091.html

Discuz!NT是一个论坛程序,是典型的互联网应用,在设计时本身就考虑了互联网应用场景下高并发高访问量的需求,在普通开源版本中,主要采用的缓存机制来提高系统的性能。

一、缓解数据库读取压力

相关文章如下:
Discuz!NT 缓存设计简析 [原创]
http://www.cnblogs.com/daizhj/archive/2007/08/15/855163.html

这个缓存机制使用的是.Net本身提供的缓存功能,System.Web.Caching.Cache
这个方案可以解决一般访问量不是很大的站点的需求,更高一级的,可以通过增加Web园工作进程来达到提升性能的需求,而且这个方案里面,已经解决多进程下缓存同步的问题。

在Discuz!NT企业版中,提供了更高层次的解决方案,使用了分布式缓存机制,引入了Memcached、Redis、LLServer,相关文章如下:

Discuz!NT中集成Memcached分布式缓存
http://www.cnblogs.com/daizhj/archive/2009/03/23/1386652.html

在Discuz!NT中进行缓存分层(本地缓存+memcached)
http://www.cnblogs.com/daizhj/archive/2009/11/17/1604436.html

Discuz!NT中的Redis架构设计

http://www.cnblogs.com/daizhj/archive/2011/02/21/1959511.html

Discuz!NT跨站缓存同步

http://www.cnblogs.com/daizhj/archive/2010/06/18/discuznt_memcache_syncdata.html

Discuz!NT中的LLServer架构设计

http://www.cnblogs.com/daizhj/archive/2011/08/26/discuznt_llserver_arch.html

Memcached是danga.com(运营LiveJournal的技术团队)开发的一套分布式内存对象缓存系统,用于在动态系统中减少数据库负载,提升性能。具体的介绍可以参考:

Memcached深度分析
http://www.cnblogs.com/luluping/archive/2009/01/14/1375456.html

通过以上的方案,能解决大部分高访问高并发的需求,因为论坛产品的特殊性,读写比大概是4:1,所以首先应该在读数据方面进行减压优化。

二、缓解Web服务器压力

Discuz!NT在缓解Web服务器压力上采用了如下的方案。

将用户上传的附件通过FTP方式传送到另外一台服务器上,相关的文章如下:
  Discuz!NT中远程附件的功能实现[FTP协议]

http://www.cnblogs.com/daizhj/archive/2008/07/28/1254648.html

  1. 通过SQUID将静态文件缓存分布
    使用SQUID做静态前端,将论坛中的大部分静态文件布署或外链到一个新的HTTP链接上,从而给Web服务器减压,提升性能。

Discuz!NT静态文件缓存(SQUID)解决方案
http://www.cnblogs.com/daizhj/archive/2010/06/10/1692758.html

三、负载均衡

通过以上的方案,Web服务器压力小了,性能也提升了,但是如果遇到更高的并发访问量,单台Web服务器还是不能满足需求,Discuz!NT采取了负载均衡的方案。使用了LVS+KEEPALIVED、NGINX等。相关文章如下:

Discuz!NT负载均衡解决方案(HA)之—LVS(Linux Virtual Server)
    http://www.cnblogs.com/daizhj/archive/2010/06/13/1693673.html

Discuz!NT负载均衡解决方案(HA)之—LVS(Linux Virtual Server)

http://www.cnblogs.com/daizhj/archive/2010/06/13/1693673.html

Discuz!NT负载均衡方案

http://www.cnblogs.com/daizhj/archive/2010/06/24/1667422.html

使用的是nginx,使用nginx作为前端负载均衡,这个确实很有吸引力,有时间能试用下就好。

四、缓解数据库压力

在Discuz!NT中,数据库作为数据持久化工具,必定在并发访问频繁且负载压力较大的情况下成为系统性能的‘瓶颈’。即使使用上面的本地缓存等方式来解决频繁访问数据库的问题,但仍旧会有大量的并发请求要访问动态数据, 其中的‘读写分离’方案就是一种被广泛采用的方案。相关文章:

Discuz!NT数据库读写分离方案

http://www.cnblogs.com/daizhj/archive/2010/06/21/dbsnap_master_slave_database.html

全文搜索方案:

Discuz!NT企业版之Sphinx全文搜索(上)

http://www.cnblogs.com/daizhj/archive/2010/06/28/discuznt_entlib_sphinx_one.html

Discuz!NT企业版之Sphinx全文搜索(下)

http://www.cnblogs.com/daizhj/archive/2010/06/30/discuznt_entlib_sphinx_two.html

处理大数据量:

Discuz!NT千万级数据量上的两驾马车–TokyoCabinet,MongoDB

http://www.cnblogs.com/daizhj/archive/2010/07/22/1781140.html

好了,上面就是Discuz!NT企业版为了提升性能采取的一系列方案,确实对asp.net互联网应用很有参考价值,其中用到的很多开源产品都是基于Linux的,如Memcached、Redis、LLServer、SQUID、NGINX、LVS、Sphinx,虽然有些产品有Windows版本,但是其性能表现能力远远比不上Linux上面,看来在Web应用上,性能方面的表现以及开源产品的研究,Linux远远的走在了Windows前面。

c# udp 高并发 相关内容

c# udp
2018-08-15 14:48:14 qq_39097425 阅读数 702

1.接收

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            UdpClient client = null;
            string receiveString = null;
            byte[] receiveData = null;
            //实例化一个远程端点,IP和端口可以随意指定,等调用client.Receive(ref remotePoint)时会将该端点改成真正发送端端点 
            IPEndPoint remotePoint = new IPEndPoint(IPAddress.Any, 0);

            while (true)
            {
                // u3d接收端口
                client = new UdpClient(9000);
                receiveData = client.Receive(ref remotePoint);//接收数据 
                receiveString = Encoding.Default.GetString(receiveData);
                Console.WriteLine(receiveString);
                client.Close();//关闭连接 
            }
        }
    }
}

 

2.发送

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace UdpClientNa
{
    class Program
    {
        static void Main(string[] args)
        {
            string sendString = null;//要发送的字符串 
            byte[] sendData = null;//要发送的字节数组 
            UdpClient client = null;

            IPAddress remoteIP = IPAddress.Parse("127.0.0.1"); //假设发送给这个IP
            // u3d发送端口 9000是发送端口
            int remotePort = 9000;
            IPEndPoint remotePoint = new IPEndPoint(remoteIP, remotePort);//实例化一个远程端点 

            while (true)
            {
                sendString = Console.ReadLine();
                sendData = Encoding.Default.GetBytes(sendString);

                client = new UdpClient();
                client.Send(sendData, sendData.Length, remotePoint);//将数据发送到远程端点 
                client.Close();//关闭连接 
            }
        }
    }
}

 

c# udp 高并发 相关内容

C# UDP
2019-03-24 14:03:36 haisong1991 阅读数 392

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace TestSocket
{
    public partial class Form1 : Form
    {
        UdpClient client = new UdpClient(0);
        UdpClient server = new UdpClient(10086);
        Thread tr;
        private int i;
        public Form1()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
            tr = new Thread(new ThreadStart(recv));
            tr.IsBackground = true;
            tr.Start();
        }

        private void recv()
        {
            IPEndPoint from = new IPEndPoint(IPAddress.Any,0);
            while (true)
            {
                byte[] buf = server.Receive(ref from);
                string msg = Encoding.Default.GetString(buf);
                textBox1.Text =textBox1.Text+ msg+Environment.NewLine;
                Thread.Sleep(2000);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            i++;
            byte[] buf = Encoding.Default.GetBytes(i.ToString());
            IPEndPoint serverAddr = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10086);
            client.Send(buf, buf.Length,serverAddr);
        }
    }
}
 

c# udp 高并发 相关内容

c# UDP
2012-04-25 20:06:24 Sniffer_Wang 阅读数 512
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;


namespace UDPClient
{
class UDPServer
{
private static IPEndPoint ip;
private static Socket newsock;




private static UDPServer instance=new UDPServer();


private UDPServer() 
{
  
}


public static UDPServer getInstance()
{
return instance;
}


public void start()
{
ip = new IPEndPoint(IPAddress.Any, 8001);
newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
newsock.Bind(ip);
}




public String recieve()
{
byte[] data = new byte[1024];
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint Remote = (EndPoint)(sender);
int length=newsock.ReceiveFrom(data, ref Remote);//获取client内容


response(Remote);


return Encoding.ASCII.GetString(data,0,length) ;
}


private void response(EndPoint remote)
{
string msg = "1";
byte[] data = Encoding.ASCII.GetBytes(msg);


newsock.SendTo(data,data.Length,SocketFlags.None,remote);
}
}
}

c# udp 高并发 相关内容

C# Udp

阅读数 3

C# Socket 高并发

阅读数 6

c# socket udp

阅读数 429

没有更多推荐了,返回首页