1.asp.net webform用“Request.PhysicalApplicationPath获取站点所在虚拟目录的物理路径,最后包含“\”; 2.c# winform用A:“Application.StartupPath”:获取当前应用程序所在目录的路径,最后不包含“\”;B:“Application.ExecutablePath ”:获取当前应用程序文件的路径,包含文件的名称;C:“AppDomain.CurrentDomain.BaseDirectory”:获取当前应用程序所在目录的路径,最后包含“\”;D:“System.Threading.Thread.GetDomain().BaseDirectory”:获取当前应用程序所在目录的路径,最后包含“\”;E:“Environment.CurrentDirectory”:获取当前应用程序的路径,最后不包含“\”;F:“System.IO.Directory.GetCurrentDirectory”:获取当前应用程序的路径,最后不包含“\”; 3.c# windows service服务中用“AppDomain.CurrentDomain.BaseDirectory”或“System.Threading.Thread.GetDomain().BaseDirectory”;用“Environment.CurrentDirectory”和“System.IO.Directory.GetCurrentDirectory”将得到“ system32”目录的路径;如果要使用“Application.StartupPath”或“Application.ExecutablePath ”,需要手动添加对“System.Windows.Forms.dll ”的引用,并在程序开头用“using System.Windows.Forms”声明该引用; 4.在卸载程序获取系统安装的目录:System.Reflection.Assembly curPath = System.Reflection.Assembly.GetExecutingAssembly();string path=curPath.Location;//得到安装程序类SetupLibrary文件的路径,获取这个文件路径所在的目录即得到安装程序的目录; System.Diagnostics.StackFrame f = new System.Diagnostics.StackFrame(1);MethodBase mb = f.GetMethod();System.Web.HttpContext.Current.Response.Write(mb.DeclaringType.ToString()); 获取调用类的信息,可以从父类知道子类的情况
View Details第一种方法: string AppPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; if (AppPath.EndsWith("\\") || AppPath.EndsWith("/")) AppPath= AppPath.Substring(0, AppPath.Length – 1); 第二种方法:string AppPath = Environment.CurrentDirectory; // 结尾不带"/" 第三种方法:string AppPath = Directory.GetCurrentDirectory();//获取应用程序的当前工作目录 Directory.SetCurrentDirectory(localFolder);
View Details相信每个编程爱好者都希望自己的程序不仅性能优越而且有一个美观的界面,一个区别于别人的程序的个性化的界面。然而以前烦琐的API调用和大量的代码使大家望而却步。现在好了,在C#中通过少量的代码就可以实现不规则窗体的制作。如果您有兴趣就接着往下看吧。 一、在说我用的方法前,我不得不说一下另一种方法,这种方法在实现不规则窗体自身显示效果(即除开窗体的移动、最大最小话、关闭等)时是不用编代码 的。非常简便,但它的致命缺点就是要要求程序运行环境在24位色以下,否则不规则窗体的透明部分就会显示出来,窗体会非常难看。 方法1:步骤1:先用图象处理软件制作您的不规则窗体的位图BMP(最好是位图,其它的我没有试过:))。制作时请注意将背景色(即需要设置成透明的颜色部分)设置成与非背景图片颜色反差较大的颜色,并且使用一种容易记忆的颜色。如下图: 图中黄颜色背景将要设置成透明部分 步骤2:新建windows应用程序。创建windows窗体并设置窗体基本属性。(1)将 FormBorderStyle 属性设置为 None。(2)将窗体的 BackgroundImage 属性设置为先前创建的位图文件。不必将文件添加到项目系统中;这将在指定该文件作为背景图像时自动完成。(3)将 TransparencyKey 属性设置为位图文件的背景色,本例中为黄色。(此属性告诉应用程序窗体中的哪些部分需要设置为透明。 )上面两个步骤已经完成了不规则窗体自身显示效果的制作,此刻您要做的就是为窗体添加移动、关闭、最大最小化的事件。这个将在方法2中详细介绍。方法1在24位色以下的环境中可以显示正常,但在24位色以上时黄色背景不能消失,所以方法1不能胜任24位色以上环境。为了解决这个问题,我们可以用到方法2。方法2步骤1:同方法1,先用图象处理软件制作您的不规则窗体的位图BMP步骤2:创建windows应用程序。创建windows窗体。由于方法2是调用类来实现制作不规则窗体,所以您只需要在窗体的LOAD事件中加入以下代码:private void login_Load(object sender, System.EventArgs e){//初始化调用不规则窗体生成代码BitmapRegion BitmapRegion =new BitmapRegion();//此为生成不规则窗体和控件的类BitmapRegion.CreateControlRegion(this,new Bitmap("HMlogin.bmp")); }其中"HMlogin.bmp"为您制作的位图。 下面就是文件BitmapRegion.cs 我在网上找到的是英文的,自己翻译了一下,英语水平有限,有错的地方还请大家指出。 /***************************************************************************************///// 功能描述:不规则窗体和控件的生成类// 撰 写 人:不祥(网上搜集)// //// 修改说明:2005.8.31 杨丹翻译和修改///***************************************************************************************/using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; { /// <summary> /// Summary description for BitmapRegion. /// </summary> public class BitmapRegion { public BitmapRegion() {} /// <summary> /// Create and apply the region on the supplied control/// 创建支持位图区域的控件(目前有button和form)/// </summary> /// <param name="control">The Control object to apply the region to控件</param> /// <param […]
View Details很多光盘上的程序,比如电脑迷光盘,开头总有一段动画,用来展现企业品牌和LOGO之用。这个动画是Flash做的,而且嵌入到程序中简直做到无缝融合,因为右键点击它也不会有那特有而烦人的Flash右键菜单。 因此将Flash融合到WinForm中能够增强程序的多媒体效果和炫丽的外观。现在我们就来看看在C#桌面程序中如何插入Flash视频,而且去掉烦人的右键菜单。 首先要插入Flash就必须使用Flash控件,在工具栏右键选择“选择项…”,然后在“COM组件”面板下点击“浏览”按钮,在本机电脑C:\WINDOWS\system32\Macromed\Flash\目录里选择Flash8.ocx(也有可能是Flash9F.ocx,版本不同所致),然后点击确定就可以了。但到这里还没有完,因为要使用Flash控件必须注册它。 在CMD里面输入如下: regsvr32 C:\WINDOWS\system32\Macromed\Flash\Flash8.ocx 系统会提示注册成功,这个时侯就可以在VS2008里面使用该控件了! 打开VS2008,新建一个Windows程序,然后把刚才我们选择的Flash控件Shockwave Flash Object拖到窗体中,这时窗体中会出现一个白色的矩形框,Name属性我们设置为Myflash,在里面可以播放我们需要的swf文件。 注意到该控件主要有几个属性: Name属性,这个是所有对象都会有的。 Menu属性,这个是Flash菜单项,默认值为true,也就是右键的时候会出现完整的Flash菜单,如果设置为False,则只出现最简的菜单(设置与关于)。 Move属性,这个属性是用来指定要播放的Flash文件的。 Playing属性,指定是否装在影片之后马上播放。 Quality属性,设置影片的质量。 Scalemode属性,设置影片的缩放模式。 Visible属性,设置影片控件的可视与否。 接下来我们在窗体中放置一个按钮,Text属性设置为LoadSwf。双击添加事件代码如下: OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Flash文件|*.swf"; DialogResult dr = ofd.ShowDialog(); if (dr == DialogResult.OK) { Myflash.Movie = ofd.FileName; Myflash.Play(); } 这样当程序运行的时候点击按钮会要我们选择一个SWF文件,选择好后确定就自动播放了! 当然,我们还可以添加一些按钮,分别为Play,Pause Play按钮的播放功能如下: This.Myflash.Play(); Pause按钮的暂停功能如下: This.Myflash.StopPlay();
View DetailsSystem.IO命名空间中的类为托管应用程序提供文件以及其他形式的输入输出。托管i/o的基本构件是流,而流是字节导向的数据的抽象表示。流通过System.IO.Stream类表示. System.IO.FileStream允许将文件作为流访问; System.IO.MemoryStream允许将内存块作为流进行访问 以下为读写文件的示例 先引用命名空间 using System.IO; 以下是源代码 namespace 文本文件打开测试{public partial class Form1 : Form{public Form1(){InitializeComponent();} private void btn_Read_Click(object sender, EventArgs e){//异常检测开始try{FileStream fs = new FileStream(@tB_PachFileName.Text , FileMode.Open, FileAccess.Read);//读取文件设定StreamReader m_streamReader = new StreamReader(fs, System.Text.Encoding.GetEncoding("GB2312"));//设定读写的编码//使用StreamReader类来读取文件m_streamReader.BaseStream.Seek(0, SeekOrigin.Begin);// 从数据流中读取每一行,直到文件的最后一行,并在rTB_Display.Text中显示出内容this.rTB_Display.Text = "";string strLine = m_streamReader.ReadLine();while (strLine != null){this.rTB_Display.Text += strLine + "\n";strLine = m_streamReader.ReadLine();}//关闭此StreamReader对象m_streamReader.Close();}catch{//抛出异常MessageBox.Show("指定文件不存在");return;}//异常检测结束 } private void btn_Replace_Click(object sender, EventArgs e){//判断替换开始if (tB_Replace.Text == ""&&tB_Replace_2.Text==""){MessageBox.Show("想替换的字符都没有就换啊,你太有才了");}else{if (rTB_Display.Text == ""){MessageBox.Show("文件内容为空无法进行替换,请检查文件");}else{string str = rTB_Display.Text.ToString();rTB_Display.Text = str.Replace(@tB_Replace.Text ,@tB_Replace_2.Text);//替换}}//结束 } private void btn_Save_Click(object sender, EventArgs […]
View Details多线程程序的开发,启动了多个线程的程序在关闭的时候却出现了问题,如果程序退出的时候不关闭线程,那么线程就会一直的存在,但是大多启动的线程都是局部变量,不能一一的关闭,如果调用Thread.CurrentThread.Abort()方法关闭主线程的话,就会出现ThreadAbortException 异常,因此这样不行。解决办法办法:Thread.IsBackground 设置线程为后台线程。msdn对前台线程和后台线程的解释:托管线程或者是后台线程,或者是前台线程。后台线程不会使托管执行环境处于活动状态,除此之外,后台线程与前台线程是一样的。一旦所有前台线程在托管进程(其中 .exe 文件是托管程序集)中被停止,系统将停止所有后台线程并关闭。通过设置 Thread.IsBackground 属性,可以将一个线程指定为后台线程或前台线程。例如,通过将 Thread.IsBackground 设置为 true,就可以将线程指定为后台线程。同样,通过将 IsBackground 设置为 false,就可以将线程指定为前台线程。从非托管代码进入托管执行环境的所有线程都被标记为后台线程。通过创建并启动新的 Thread 对象而生成的所有线程都是前台线程。如果要创建希望用来侦听某些活动(如套接字连接)的前台线程,则应将 Thread.IsBackground 设置为 true,以便进程可以终止。所以解决办法就是在主线程初始化的时候,设置:Thread.CurrentThread.IsBackground = true;这样,主线程就是后台线程,在关闭主程序的时候就会关闭主线程,从而关闭所有线程。但是这样的话,就会强制关闭所有正在执行的线程,所以在关闭的时候要对线程工作的结果保存 from url http://www.cnblogs.com/king_dy/archive/2010/12/02/1894147.html
View Details在实例化Thread的实例,需要提供一个委托,在实例化这个委托时所用到的参数是线程将来启动时要运行的方法。在.net中提供了两种启动线程的方式,一种是不带参数的启动方式,另一种是带参数的启动的方式。 不带参数的启动方式 如果启动参数时无需其它额外的信息,可以使用ThreadStart来实例化Thread,如下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
using System; using System.Threading; namespace StartThread { class Program { int interval = 200; static void Main(string[] args) { Program p = new Program(); Thread nonParameterThread = new Thread(new ThreadStart(p.NonParameterRun)); nonParameterThread.Start(); } /// <summary> /// 不带参数的启动方法 /// </summary> public void NonParameterRun() { for (int i = 0; i < 10; i++) { Console.WriteLine("系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString()); Thread.Sleep(interval); //让线程暂停 } } } } |
程序的运行效果我们不用运行也会知道,那就是在循环中将系统当前时间的毫秒部分输出出来,在每次输出之后会将当前线程暂停一下,直到10次之后运行完毕,终止线程的执行。 在上面的代码中我们是通过定义全局变量的方法来指定线程暂停间隔,按照这种方法,假如要运行10个线程,每个线程的暂停间隔不一样的话,就需要定义10个全局变量,虽然最终不影响系统的运行效果,但是总觉得不是太爽。 有没有比较简单一点的办法呢?有!那就是使用带参数的启动方法。 带参数的启动方法 如果要在实例化线程时要带一些参数,就不能用ThreadStart委托作为构造函数的参数来实例化Thread了,而要 ParameterizedThreadStart委托,和ThreadStart一样的是它也是线程启动时要执行的方法,和ThreadStart不同的是,它在实例化时可以用一个带有一个Object参数的方法作为构造函数的参数,而实例化ThreadStart时所用到的方法是没有参数的。 为什么是Object这样的参数呢?很简单,因为在.net中Object是所有类型的基类,用它可以表示Array(数组)、Interface(接口)、ValueType(值类型,如bool,byte,char,short,int,float,long,double等)、class(类)等.net中的类型。当然,这也意味着如果你要启动一个线程,给它传递一个int类型参数时,必须在启动方法中进行相应的类型转换。 下面就是一个例子,在启动线程时指定了线程的暂停间隔,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace StartThread { class Program { int interval = 200; static void Main(string[] args) { Program p = new Program(); Thread parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun)); parameterThread.Name = "Thread A:"; parameterThread.Start(30); } /// <summary> /// 带参数的启动方法 /// </summary> /// <param name="ms">让线程在运行过程中的休眠间隔</param> public void ParameterRun(object ms) { int j = 10; int.TryParse(ms.ToString(), out j);//这里采用了TryParse方法,避免不能转换时出现异常 for (int i = 0; i < 10; i++) { Console.WriteLine(Thread.CurrentThread.Name + "系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString()); Thread.Sleep(j);//让线程暂停 } } } } |
在这个方法里,我们在启动线程时顺便指定了线程的暂停间隔,也就是这句: parameterThread.Start(30); 线程启动时运行的方法是public void ParameterRun(object ms),这个值为30的int类型变量被装箱成object,所以在方法中还需要将它转换成int类型,这个可以通过拆箱或者其它办法解决。 假如我们要启动两个线程,每个线程的暂停间隔不一样,启动代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace StartThread { class Program { int interval = 200; static void Main(string[] args) { Program p = new Program(); Thread parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun)); parameterThread.Name = "Thread A:"; parameterThread.Start(30); //启动第二个线程 parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun)); parameterThread.Name = "Thread B:"; parameterThread.Start(60); } /// <summary> /// 带参数的启动方法 /// </summary> /// <param name="ms">让线程在运行过程中的休眠间隔</param> public void ParameterRun(object ms) { int j = 10; int.TryParse(ms.ToString(), out j);//这里采用了TryParse方法,避免不能转换时出现异常 for (int i = 0; i < 10; i++) { Console.WriteLine(Thread.CurrentThread.Name + "系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString()); Thread.Sleep(j);//让线程暂停 } } } } |
对上面的代码做一点说明,就是线程启动之后,线程的实例不必再存在,例如在上面的代码中我用的是同一个实例实例化了两个线程,并且这两个线程运行很正常。 继续探索 上面解决了一个问题,如果在启动线程时需要参数如何解决,如果针对上面的问题继续发掘,比如:在启动线程时不但要指定线程的暂停间隔,还需要指定循环次数(在上面的所有例子中都是执行10次的),这个问题该如何解决呢? 有两种办法可以解决: 首先可以继续在ParameterizedThreadStart这里做文章,因为这里可以使用一个Object类型的参数,那么可以通过数组或者一个类来解决(因为它们都是Object的子类)。我在做某个系统时确实采用数组处理过这种情况,这样就要求在线程启动方法中必须清楚知道数组中每个参数的用途,不是太方便。 这里说说重新定义一个实体类来解决的方法,代码如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace StartThread { class MyThreadParameter { private int interval; private int loopCount; /// <summary> /// 循环次数 /// </summary> public int LoopCount { get { return loopCount; } } /// <summary> /// 线程的暂停间隔 /// </summary> public int Interval { get { return interval; } } /// <summary> /// 构造函数 /// </summary> /// <param name="interval">线程的暂停间隔</param> /// <param name="loopCount">循环次数</param> public MyThreadParameter(int interval, int loopCount) { this.interval = interval; this.loopCount = loopCount; } } class Program { int interval = 200; static void Main(string[] args) { Program p = new Program(); Thread parameterThread = new Thread(new ParameterizedThreadStart(p.MyParameterRun)); parameterThread.Name = "Thread A:"; MyThreadParameter paramter = new MyThreadParameter(50, 20); parameterThread.Start(paramter); } /// <summary> /// 带多个参数的启动方法 /// </summary> /// <param name="ms">方法参数</param> public void MyParameterRun(object ms) { MyThreadParameter parameter = ms as MyThreadParameter;//类型转换 if (parameter != null) { for (int i = 0; i < parameter.LoopCount; i++) { Console.WriteLine(Thread.CurrentThread.Name + "系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString()); Thread.Sleep(parameter.Interval);//让线程暂停 } } } } } |
第二种方法和上面方法有些相似,也是需要引入外部类,并且将Thread实例放在引入的类中,这种情况适合于在线程中处理的业务逻辑比较复杂的情况。在前不久处理的一个项目中我用过这种情况,它是用来实现双向数据传输的。 如果实现上面的效果,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace StartThread { class MyThreadParameter { private int interval; private int loopCount; private Thread thread; /// <summary> /// 构造函数 /// </summary> /// <param name="interval">线程的暂停间隔</param> /// <param name="loopCount">循环次数</param> public MyThreadParameter(int interval, int loopCount) { this.interval = interval; this.loopCount = loopCount; thread = new Thread(new ThreadStart(Run)); } public void Start() { if (thread != null) { thread.Start(); } } private void Run() { for (int i = 0; i < loopCount; i++) { Console.WriteLine("系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString()); Thread.Sleep(interval);//让线程暂停 } } } class Program { static void Main(string[] args) { MyThreadParameter parameterThread = new MyThreadParameter(30, 50); parameterThread.Start(); } } } |
上面的代码的运行效果和前面的代码运行效果类似,只不过是将业务处理代码放在一个单独的类MyThreadParameter中,使得MyThreadParameter看起来也像一个Thread,实际上维护的还是其内部的Thread,在一些大型系统中这样做的好处是便于维护。 总结:在本篇主要讲述如何启动线程的问题,在启动时可能会遇到无需参数、需要多个参数的情况,在这里讲述了如何解决这些问题的思路。在.net类库中虽然存在着庞大的类库,但是并不是总会有合适的类来解决我们所遇到的问题,但是只要肯动脑筋总会想到合适的办法。
View Details我们在使用C# TextBox进行开发操作的时候经常会碰到C# TextBox的使用,那么C# TextBox的使用有没有一些常用的技巧呢?如C# TextBox换行的处理,其实就是一些常用的操作,那么这里就向你介绍几个我们常见的需求以及解决方法。 一、关于C# TextBox全选的判断: int SelectLength=this.textBox1.SelectionLength;//获取选中的字符长度 if (SelectLength == this.textBox1.Text.Length) {//判断是否全部选中 MessageBox.Show("你已经选中"); } 二、关于C# TextBox换行、设置光标位置、随文本滚动 ◆C# TextBox换行 TextBoxControl.Text += Environment.NewLine; 如何在多行TextBox中写入文本时实现换行?由于Windows系统中,回车符需两上字符。因此方法是使用\r\n标记,如 Label="Calculation " ":…….SUM\r\n"; textBox.AppendText(Label); 另外更有一个办法是用Environment.Newline的方法,能够兼容Windows和Linux系统。 ◆C# TextBox设置光标位置到文本最后 TextBoxControl.SelectionStart = TextBoxControl.TextLength; ◆C# TextBox随文本滚动 TextBoxControl.ScrollToCaret(); 如何在多行TextBox中用滚动条,使添加文本后自动滚动显示到最后一行?方法是使用ScrollToCaret方法,自动滚动到插入符的位置,如: textBox.AppendText(Label); textBox.ScrollToCaret(); 那么对于C# TextBox常用操作的内容就向你介绍到这里,希望对你了解和学习C# TextBox的使用有所帮助。 转自:http://blog.sina.com.cn/s/blog_43eb83b90100l18v.html
View Details大家好,这是我最近写了一个Udp通信的小程序,发表出来和大家共同学习,我希望和大家共同进步。 upd通信接受端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
using System; using System.Net; using System.Net.Sockets; namespace Zhty.Socket.UDPSocket { public class UDP_Client { #region 属性 private IPAddress _ClientAddress = IPAddress.Any; private int _ClientPort = 0; private byte[] _data = new byte[] { }; public IPEndPoint Client { get { return new IPEndPoint(_ClientAddress, _ClientPort); } set { _ClientAddress = value.Address; _ClientPort = value.Port; } } public IPAddress ClientAddress { get { return _ClientAddress; } set { _ClientAddress = value; } } public int ClientPort { get { return _ClientPort; } set { _ClientPort = value; } } #endregion #region 方法 public void SendMessage(byte[] message) { // Encode message per settings // Send the message _data = message; try { SendUDPMessage(_data); } catch (Exception ex) { throw ex; } } private int SendUDPMessage(Byte[] _data) { //' Create a UDP Server and send the message, then clean up UdpClient _UDPServer = null; int ReturnCode; try { _UDPServer = new UdpClient(); ReturnCode = 0; _UDPServer.Connect(Client); ReturnCode = _UDPServer.Send(_data, _data.Length); } catch (Exception ex) { throw ex; } finally { if (_UDPServer != null) { _UDPServer.Close(); } } return ReturnCode; } #endregion } } |
udp通信的发送端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.Net.Sockets; using System.Net; namespace Zhty.Socket.UDPSocket { public class UDP_Server { private Thread _ThreadReceive; private int _ClientPort = 0; private string _Message = null; private UdpClient _UDPClient; private IPEndPoint _Server = new IPEndPoint(IPAddress.Any, 0); private int _BytesReceived = 0; #region 事件定义 public delegate void OnReceivedDataHandler(object sender, DataReceivedEventArgs e); public event OnReceivedDataHandler OnRecivedData; public delegate void OnStateChangedHandler(object sender, ServerStateChangeEventArgs e); public event OnStateChangedHandler OnStateChanged; #endregion #region 属性 int _bufferSize = 1024; public int BufferSize { get { return _bufferSize; } set { _bufferSize = value; } } public int BytesReceived { get { return _BytesReceived; } } public string Message { get { return _Message; } } public int ClientPort { get { return _ClientPort; } set { _ClientPort = value; } } #endregion #region 方法 void DataReceiveProc() { //BeforeReceive(this,new EventArgs()); _Message = ""; byte[] data = new byte[BufferSize]; try { data = _UDPClient.Receive(ref _Server); if (OnRecivedData != null) OnRecivedData(this, new DataReceivedEventArgs(data)); Thread.Sleep(100); } catch (Exception ex) { if (OnStateChanged != null) OnStateChanged(this, new ServerStateChangeEventArgs(false)); throw ex; } finally { InitializeThread(); } } private void InitializeClient() { if (_UDPClient == null) { this._UDPClient = new UdpClient(ClientPort); } } private void InitializeThread() { try { _ThreadReceive = new Thread(new ThreadStart(DataReceiveProc)); _ThreadReceive.Start(); } catch (Exception ex) { throw ex; } } public void Start() { InitializeClient(); InitializeThread(); } #endregion public void Stop() { try { _ThreadReceive.Abort(); if (_UDPClient != null) { // ' Close the UDPClient and then force it to Nothing _UDPClient.Close(); _UDPClient = null; } } catch (Exception ex) { throw ex; } } #region 析构方法 ~UDP_Server() { Stop(); } #endregion } } |
辅助类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
using System; using System.Collections.Generic; using System.Text; namespace Zhty.Socket.UDPSocket { public class DataReceivedEventArgs : EventArgs { public DataReceivedEventArgs(byte[] data) { Data = data; } byte[] m_Data; public byte[] Data { get { return m_Data; } set { m_Data = value; } } } public class ServerStateChangeEventArgs : EventArgs { public ServerStateChangeEventArgs(bool state) { Running = state; } bool m_Running; public bool Running { get { return m_Running; } set { m_Running = value; } } } } |
转自:http://www.cnblogs.com/zhaotianyu001/articles/549259.html
View DetailsInternet协议族中有支持无连接的传输协议,即UDP协议。UDP协议提供了一种方法来发送经过封装的IP数据报,而且不必建立连接就 可以发送这些IP数据报。 服务器端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
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); } } } } |
客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
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 实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
// 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 […]
View Details