精华内容
下载资源
问答
  • 学习C#编写软件注册与注册机
  • C#编写软件要实现,若以管理员权限登陆且规定时间无操作,设备需自动退出登陆,有什么好的方法实现呢
  • C#编写软件自动升级更新程序

    千次阅读 2012-12-08 20:59:08
    下面我为大家提供了一套可复用的用C#编写的自动升级系统。 2 实现软件的自动升级存在的困难  第一,为了查找远程服务器上的更新,应用程序必须有查询网络的途径,这需要网络编程、简单的应用程序与服务器...

    文章整理!

    1 前言

     长期以来,广大程序员为到底是使用Client/Server,还是使用Browser/Server结构争论不休,在这些争论当中,C/S结构的程序可维护性差,布置困难,升级不方便,维护成本高就是一个相当重要的因素。有很多企业用户就是因为这个原因而放弃使用C/S。然而当一个应用必须要使用C/S结构才能很好的实现其功能的时候,我们该如何解决客户端的部署与自动升级问题?部署很简单,只要点击安装程序即可,难的在于每当有新版本发布时,能够实现自动升级[3]。现在好了,我们的目标很简单,我们希望开发一个与具体应用无关的能够复用的自动升级系统。下面我为大家提供了一套可复用的用C#编写的自动升级系统。

    2 实现软件的自动升级存在的困难

     第一,为了查找远程服务器上的更新,应用程序必须有查询网络的途径,这需要网络编程、简单的应用程序与服务器通讯的协议。

     第二是下载。下载看起来不需要考虑联网的问题,但要考虑下载用户请求的文件,以及在没有用户同意时下载大文件。友好的自动更新应用程序将使用剩余的带宽下载更新。这听起来简单,但却是一个技术难题,幸运的是已经有了解决方法。


     第三个考虑因素是使用新版应用程序更换原应用程序的过程。这个问题比较有趣,因为它要求代码运行时将自己从系统删除,有多种办法可以实现该功能[5],本文程序主要通过比较新旧版本的日期号来实现替换新版本应用程序的功能。

     

    3 实现软件自动在线升级的原理

     写两个程序,一个是主程序;一个是升级程序;所有升级任务都由升级程序完成。

     1.启动升级程序,升级程序连接到网站,下载新的主程序(当然还包括支持的库文件、XML配置文档等)到临时文件夹;

     2.升级程序获取服务器端XML配置文件中新版本程序的更新日期或版本号或文件大小;

     3.升级程序获取原有客户端应用程序的最近一次更新日期或版本号或文件大小,两者进行比较;如果发现升级程序的日期大于原有程序的最新日期,则提示用户是否升级;或者是采用将现有版本与最新版本作比较,发现最新的则提示用户是否升级;也有人用其它属性如文件大小进行比较,发现升级程序的文件大小大于旧版本的程序的大小则提示用户升级。本文主要采用比较新旧版本更新日期号来提示用户升级。

     4.如果用户选择升级,则获取下载文件列表,开始进行批量下载文档;

     5.升级程序检测旧的主程序是否活动,若活动则关闭旧的主程序;

     6.删除旧的主程序,拷贝临时文件夹中的文件到相应的位置;

     7.检查主程序的状态,若状态为活动的,则启动新的主程序;

     8.关闭升级程序,升级完成[4]。  


    4 用C#实现在线升级的关键步骤


    这里我主要使用日期信息来检测是否需要下载升级版本。 
    4.1 准备一个XML配置文件 
    名称为AutoUpdater.xml,作用是作为一个升级用的模板,显示需要升级的信息。

    <?xml version="1.0" encoding="utf-8" ?>                  //xml版本号 
    <AutoUpdater> 
    	<URLAddres URL="http://pan.baidu.com/share/link?shareid=138673&uk=271024850/"/>//升级文件所在服务器端的网址 
    	<UpdateInfo> 
    		<UpdateTime Date = "2012-12-08"/>           //升级文件的更新日期 
    		<Version Num = "1.0.1.2"/>                //升级文件的版本号 
    	</UpdateInfo> 
    	<UpdateFileList>                    //升级文件列表 
    		<UpdateFile FileName = "aa.txt"/>                     //共有三个文件需升级
    		<UpdateFile FileName = "VB40.rar"/> 
    		<UpdateFile FileName = "VB4-1.CAB"/> 
    	</UpdateFileList> 
    	<RestartApp>                    
    		<ReStart Allow = "Yes"/>                 //允许重新启动应用程序 
    		<AppName Name = "TIMS.exe"/>               //启动的应用程序名 
    	</RestartApp> 
    </AutoUpdater>

     从以上XML文档中可以得知升级文档所在服务器端的地址、升级文档的更新日期、需要升级的文件列表,其中共有三个文件需升级:aa.txt、VB40.rar、VB4-1.CAB。以及是否允许重新启动应用程序和重新启动的应用程序名。

    4.2 获取客户端应用程序及服务器端升级程序的最近一次更新日期 
    通过GetTheLastUpdateTime()函数来实现。


            private string GetTheLastUpdateTime(string Dir)
            {
                string LastUpdateTime = "";
                string AutoUpdaterFileName = Dir + @"\AutoUpdater.xml";
                if (!File.Exists(AutoUpdaterFileName))
                    return LastUpdateTime;
                //打开xml文件 
                FileStream myFile = new FileStream(AutoUpdaterFileName, FileMode.Open);
                //xml文件阅读器 
                XmlTextReader xml = new XmlTextReader(myFile);
                while (xml.Read())
                {
                    if (xml.Name == "UpdateTime")
                    {
                        //获取升级文档的最后一次更新日期 
                        LastUpdateTime = xml.GetAttribute("Date");
                        break;
                    }
                }
                xml.Close();
                myFile.Close();
                return LastUpdateTime;
            } 

     通过XmlTextReader打开XML文档,读取更新时间从而获取Date对应的值,即服务器端升级文件的最近一次更新时间。

    函数调用实现: 
    //获取客户端指定路径下的应用程序最近一次更新时间 
    string thePreUpdateDate = GetTheLastUpdateTime(Application.StartupPath); 
    Application.StartupPath指客户端应用程序所在的路径。

    //获得从服务器端已下载文档的最近一次更新日期 
    string theLastsUpdateDate = GetTheLastUpdateTime(theFolder.FullName); 
         theFolder.FullName指在升级文档下载到客户机上的临时文件夹所在的路径。

    4.3 比较日期 
       客户端应用程序最近一次更新日期与服务器端升级程序的最近一次更新日期进行比较。

    //获得已下载文档的最近一次更新日期 
    string theLastsUpdateDate = GetTheLastUpdateTime(theFolder.FullName); 
    if(thePreUpdateDate != "") 
    { 
    //如果客户端将升级的应用程序的更新日期大于服务器端升级的应用程序的更新日期 
    if(Convert.ToDateTime(thePreUpdateDate)>=Convert.ToDateTime(theLastsUpdateDate)) 
    { 
    MessageBox.Show("当前软件已经是最新的,无需更新!","系统提示",MessageBoxButtons.OK,MessageBoxIcon.Information); 
    this.Close(); 
    } 
    } 
       this.labDownFile.Text = "下载更新文件"; 
       this.labFileName.Refresh(); 
       this.btnCancel.Enabled = true; 
       this.progressBar.Position = 0; 
       this.progressBarTotal.Position = 0; 
       this.progressBarTotal.Refresh(); 
    
    
       this.progressBar.Refresh();
    
    //通过动态数组获取下载文件的列表 
    ArrayList List = GetDownFileList(GetTheUpdateURL(),theFolder.FullName); 
    string[] urls = new string[List.Count]; 
    List.CopyTo(urls, 0);  

    //获得已下载文档的最近一次更新日期 
    string theLastsUpdateDate = GetTheLastUpdateTime(theFolder.FullName); 
    if(thePreUpdateDate != "") 

    //如果客户端将升级的应用程序的更新日期大于服务器端升级的应用程序的更新日期 

    //获得已下载文档的最近一次更新日期 
    string theLastsUpdateDate = GetTheLastUpdateTime(theFolder.FullName); 
    if(thePreUpdateDate != "") 
    { 
        //如果客户端将升级的应用程序的更新日期大于服务器端升级的应用程序的更新日期 
        if(Convert.ToDateTime(thePreUpdateDate)>=Convert.ToDateTime(theLastsUpdateDate)) 
        { 
            MessageBox.Show("当前软件已经是最新的,无需更新!","系统提示",MessageBoxButtons.OK,MessageBoxIcon.Information); 
            this.Close(); 
        } 
    } 
       this.labDownFile.Text = "下载更新文件"; 
       this.labFileName.Refresh(); 
       this.btnCancel.Enabled = true; 
       this.progressBar.Position = 0; 
       this.progressBarTotal.Position = 0; 
       this.progressBarTotal.Refresh(); 
    
    
       this.progressBar.Refresh();
    
    //通过动态数组获取下载文件的列表 
    ArrayList List = GetDownFileList(GetTheUpdateURL(),theFolder.FullName); 
    string[] urls = new string[List.Count]; 
    List.CopyTo(urls, 0); 

       将客户端升级的应用程序的日期与服务器端下载的应用程序日期进行比较,如果前者大于后者,则不更新;如果前者小于后者,则通过动态数组获取下载文件的列表,开始下载文件。


    通过BatchDownload()函数来实现。升级程序检测旧的主程序是否活动,若活动则关闭旧的主程序;删除旧的主程序,拷贝临时文件夹中的文件到相应的位置;检查主程序的状态,若状态为活动的,则启动新的主程序。

    private void BatchDownload(object data) 
    { 
    	this.Invoke(this.activeStateChanger, new object[]{true, false}); 
    	try 
    	{ 
    		DownloadInstructions instructions = (DownloadInstructions) data; 
    		//批量下载 
    		using(BatchDownloader bDL = new BatchDownloader()) 
    		{ 
    			bDL.CurrentProgressChanged += new DownloadProgressHandler(this.SingleProgressChanged); 
    			bDL.StateChanged += new DownloadProgressHandler(this.StateChanged); 
    			bDL.FileChanged += new DownloadProgressHandler(bDL_FileChanged); 
    			bDL.TotalProgressChanged += new DownloadProgressHandler(bDL_TotalProgressChanged); 
    			bDL.Download(instructions.URLs, instructions.Destination, (ManualResetEvent) this.cancelEvent); 
    		} 
    	} 
    	catch(Exception ex) 
    	{ 
    	   ShowErrorMessage(ex); bitsCN_com 
    	} 
    	this.Invoke(this.activeStateChanger, new object[]{false, false}); 
    	this.labFileName.Text = ""; 
    	//更新程序 
    	if(this._Update) 
    	{ 
    		//关闭原有的应用程序 
    		this.labDownFile.Text = "正在关闭程序...."; 
    		System.Diagnostics.Process[]proc=System.Diagnostics.Process.GetProcessesByName("TIMS");
    		//关闭原有应用程序的所有进程 
    		foreach(System.Diagnostics.Process pro in proc) 
    		{ 
    			pro.Kill(); 
    		} 
    		DirectoryInfo theFolder=new DirectoryInfo(Path.GetTempPath()+"JurassicUpdate"); 
    		if(theFolder.Exists) 
    		{ 
    			foreach(FileInfo theFile in theFolder.GetFiles()) 
    			{ 
    				//如果临时文件夹下存在与应用程序所在目录下的文件同名的文件,则删除应用程序目录下的文件 
    				if(File.Exists(Application.StartupPath + \\"+Path.GetFileName(theFile.FullName))) 
    				File.Delete(Application.StartupPath + "\\"+Path.GetFileName(theFile.FullName)); 
    				//将临时文件夹的文件移到应用程序所在的目录下 
    				File.Move(theFile.FullName,Application.StartupPath + \\"+Path.GetFileName(theFile.FullName)); 
    			} 
    		} 
    		//启动安装程序  
    		this.labDownFile.Text = "正在启动程序...."; 
    		System.Diagnostics.Process.Start(Application.StartupPath + "\\" + "TIMS.exe"); 
    		this.Close(); 
    	} 
    }   
     


    这段程序是实现在线升级的关键代码,步骤有点复杂:首先用Invoke方法同步调用状态改变进程,然后调用动态链接库中批量下载(BatchDownloader.cs)类启动批量下载,接着判断原有的主应用程序有没有关闭,如果没关闭,则用Process.Kill()来关闭主程序。接下来,判断临时文件夹下(即下载升级程序所在的目录)是否存在与应用程序所在目录下的文件同名的文件,如果存在同名文件,则删除应用程序目录下的文件,然后将临时文件夹的文件移到应用程序所在的目录下。最后重新启动主应用程序。这样更新就完成了。  


    参考资料

    C# 实现软件自动更新升级程序# 实现软件自动更新升级程序


    展开全文
  • C#编写录音软件源码
  • C# 编写的聊天软件

    2018-08-24 11:17:15
    使用C#编写的聊天软件,初学者可以通过这个程序更快的熟悉C# 语言。
  • C#编写QQ接口软件

    2012-10-10 16:30:50
    C#编写QQ接口软件
  • C#编写截图软件

    2013-07-11 00:33:12
    根据网上高手的教程,使用GDI+编写的屏幕截图软件 使用VS2010环境
  • c#编写的绘图软件源码,可以绘制简单几何图形,也有保存导入功能,适合工程类项目开发学习!
  • DES加密软件 C#编写

    2012-06-16 01:34:41
    DES加密软件 C#编写
  • C#编写的CRC校验软件

    2018-04-13 09:34:13
    C#编写的CRC校验软件源码 支持CRC8 CRC16 CRC32校验 查表法校验
  • C#编写测试软件程序

    2016-02-23 09:03:59
    用于生产的C#控制仪器仪表的测试软件,可以直接在普赛斯仪表上使用
  • c#编写的ftp软件

    2008-12-29 09:58:58
    c#编写的ftp软件,可以模拟文件传输过程。
  • C#编写12306登录小软件

    2014-03-13 23:33:59
    C#模拟编写12306登录小软件
  • C#编写的配筋计算软件,全部代码由C#编写,vs2005开发。
  • C#编写的基础计算软件,全部由C#编写,由vs 2005开发。
  • C#_C#编写的CRC校验软件

    千次阅读 2018-04-12 20:43:16
    C#编写的CRC校验软件,模仿“格西CRC计算器 1.0”,使用查表法1.CRC8校验主要代码2.CRC16主要代码3.CRC32主要代码大端和小端的不同处理效果大端:小端:

    C#编写的CRC校验软件,模仿“格西CRC计算器 1.0”,使用查表法



    1.CRC8校验主要代码



    2.CRC16主要代码



    3.CRC32主要代码




    大端和小端的不同处理效果

    大端:


    小端:


    展开全文
  • C# 编写的时间判断软件!代码思路清晰,非常适合初学C# 的同学使用!
  • c#编写仿qq聊天软件

    2009-07-18 09:02:15
    c#编写仿qq聊天软件 基本功能实现齐全 包括服务器编写部分
  • c#编写的系统监控软件,类似于杀毒软件的监控,可以知道被监控目录下进行过哪些操作
  • 1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text;... 8 usi...
      1 using System;
      2 using System.Collections.Generic;
      3 using System.ComponentModel;
      4 using System.Data;
      5 using System.Drawing;
      6 using System.Linq;
      7 using System.Text;
      8 using System.Windows.Forms;
      9 using System.Net.Sockets;
     10 using System.Net;
     11 using System.IO;
     12 using System.Threading;
     13 
     14 namespace SyncChatClient
     15 {
     16     public partial class MainForm : Form
     17     {
     18         private string ServerIP; //IP
     19         private int port;   //端口
     20         private bool isExit = false;
     21         private TcpClient client;
     22         private BinaryReader br;
     23         private BinaryWriter bw;
     24         public MainForm()
     25         {
     26             InitializeComponent();
     27             Random r = new Random((int)DateTime.Now.Ticks);
     28             txt_UserName.Text = "user" + r.Next(100, 999);
     29             lst_OnlineUser.HorizontalScrollbar = true;
     30             SetServerIPAndPort();
     31         }
     32 
     33         /// <summary>
     34         /// 根据当前程序目录的文本文件‘ServerIPAndPort.txt’内容来设定IP和端口
     35         /// 格式:127.0.0.1:8885
     36         /// </summary>
     37         private void SetServerIPAndPort()
     38         {
     39             try
     40             {
     41                 FileStream fs = new FileStream("ServerIPAndPort.txt", FileMode.Open);
     42                 StreamReader sr = new StreamReader(fs);
     43                 string IPAndPort = sr.ReadLine();
     44                 ServerIP = IPAndPort.Split(':')[0]; //设定IP
     45                 port = int.Parse(IPAndPort.Split(':')[1]); //设定端口
     46                 sr.Close();
     47                 fs.Close();
     48             }
     49             catch (Exception ex)
     50             {
     51                 MessageBox.Show("配置IP与端口失败,错误原因:" + ex.Message);
     52                 Application.Exit();
     53             }
     54         }
     55 
     56         /// <summary>
     57         /// 【登陆】按钮事件
     58         /// </summary>
     59         /// <param name="sender"></param>
     60         /// <param name="e"></param>
     61         private void btn_Login_Click(object sender, EventArgs e)
     62         {
     63             btn_Login.Enabled = false;
     64             try
     65             {
     66                 //此处为方便演示,实际使用时要将Dns.GetHostName()改为服务器域名
     67                 //IPAddress ipAd = IPAddress.Parse("182.150.193.7");
     68                 client = new TcpClient();
     69                 client.Connect(IPAddress.Parse(ServerIP), port);
     70                 AddTalkMessage("连接成功");
     71             }
     72             catch(Exception ex)
     73             {
     74                 AddTalkMessage("连接失败,原因:" + ex.Message);
     75                 btn_Login.Enabled = true;
     76                 return;
     77             }
     78             //获取网络流
     79             NetworkStream networkStream = client.GetStream();
     80             //将网络流作为二进制读写对象
     81             br = new BinaryReader(networkStream);
     82             bw = new BinaryWriter(networkStream);
     83             SendMessage("Login," + txt_UserName.Text);
     84             Thread threadReceive = new Thread(new ThreadStart(ReceiveData));
     85             threadReceive.IsBackground = true;
     86             threadReceive.Start();
     87         }
     88 
     89         /// <summary>
     90         /// 处理服务器信息
     91         /// </summary>
     92         private void ReceiveData()
     93         {
     94             string receiveString = null;
     95             while (isExit == false)
     96             {
     97                 try
     98                 {
     99                     //从网络流中读出字符串
    100                     //此方法会自动判断字符串长度前缀,并根据长度前缀读出字符串
    101                     receiveString = br.ReadString();
    102                 }
    103                 catch
    104                 {
    105                     if (isExit == false)
    106                     {
    107                         MessageBox.Show("与服务器失去连接");
    108                     }
    109                     break;
    110                 }
    111                 string[] splitString = receiveString.Split(',');
    112                 string command = splitString[0].ToLower();
    113                 switch (command)
    114                 {
    115                     case "login":   //格式: login,用户名
    116                         AddOnline(splitString[1]);
    117                         break;
    118                     case "logout":  //格式: logout,用户名
    119                         RemoveUserName(splitString[1]);
    120                         break;
    121                     case "talk":    //格式: talk,用户名,对话信息
    122                         AddTalkMessage(splitString[1] + ":\r\n");
    123                         AddTalkMessage(receiveString.Substring(splitString[0].Length + splitString[1].Length+2));
    124                         break;
    125                     default:
    126                         AddTalkMessage("什么意思啊:" + receiveString);
    127                         break;
    128                 }
    129             }
    130             Application.Exit();
    131         }
    132 
    133         /// <summary>
    134         /// 向服务端发送消息
    135         /// </summary>
    136         /// <param name="message"></param>
    137         private void SendMessage(string message)
    138         {
    139             try
    140             {
    141                 //将字符串写入网络流,此方法会自动附加字符串长度前缀
    142                 bw.Write(message);
    143                 bw.Flush();
    144             }
    145             catch
    146             {
    147                 AddTalkMessage("发送失败");
    148             }
    149         }
    150 
    151         private delegate void AddTalkMessageDelegate(string message);
    152         /// <summary>
    153         /// 在聊天对话框(txt_Message)中追加聊天信息
    154         /// </summary>
    155         /// <param name="message"></param>
    156         private void AddTalkMessage(string message)
    157         {
    158             if (txt_Message.InvokeRequired)
    159             {
    160                 AddTalkMessageDelegate d = new AddTalkMessageDelegate(AddTalkMessage);
    161                 txt_Message.Invoke(d, new object[] { message });
    162             }
    163             else
    164             {
    165                 txt_Message.AppendText(message + Environment.NewLine);
    166                 txt_Message.ScrollToCaret();
    167             }
    168         }
    169 
    170         private delegate void AddOnlineDelegate(string message);
    171         /// <summary>
    172         /// 在在线框(lst_Online)中添加其他客户端信息
    173         /// </summary>
    174         /// <param name="userName"></param>
    175         private void AddOnline(string userName)
    176         {
    177             if (lst_OnlineUser.InvokeRequired)
    178             {
    179                 AddOnlineDelegate d = new AddOnlineDelegate(AddOnline);
    180                 lst_OnlineUser.Invoke(d, new object[] { userName });
    181             }
    182             else
    183             {
    184                 lst_OnlineUser.Items.Add(userName);
    185                 lst_OnlineUser.SelectedIndex = lst_OnlineUser.Items.Count - 1;
    186                 lst_OnlineUser.ClearSelected();
    187             }
    188         }
    189 
    190         private delegate void RemoveUserNameDelegate(string userName);
    191         /// <summary>
    192         /// 在在线框(lst_Online)中移除不在线的客户端信息
    193         /// </summary>
    194         /// <param name="userName"></param>
    195         private void RemoveUserName(string userName)
    196         {
    197             if (lst_OnlineUser.InvokeRequired)
    198             {
    199                 RemoveUserNameDelegate d = new RemoveUserNameDelegate(RemoveUserName);
    200                 lst_OnlineUser.Invoke(d, userName);
    201             }
    202             else
    203             {
    204                 lst_OnlineUser.Items.Remove(userName);
    205                 lst_OnlineUser.SelectedIndex = lst_OnlineUser.Items.Count - 1;
    206                 lst_OnlineUser.ClearSelected();
    207             }
    208         }
    209 
    210         /// <summary>
    211         /// 【发送】按钮单击事件
    212         /// </summary>
    213         /// <param name="sender"></param>
    214         /// <param name="e"></param>
    215         private void btn_Send_Click(object sender, EventArgs e)
    216         {
    217             if (lst_OnlineUser.SelectedIndex != -1)
    218             {
    219                 SendMessage("Talk," + lst_OnlineUser.SelectedItem + "," + txt_SendText.Text + "\r\n");
    220                 txt_SendText.Clear();
    221             }
    222             else
    223             {
    224                 MessageBox.Show("请先在【当前在线】中选择一个对话着");
    225             }
    226         }
    227 
    228         /// <summary>
    229         /// 窗体关闭事件
    230         /// </summary>
    231         /// <param name="sender"></param>
    232         /// <param name="e"></param>
    233         private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    234         {
    235             //未与服务器连接前 client 为 null
    236             if (client != null)
    237             {
    238                 try
    239                 {
    240                     SendMessage("Logout," + txt_UserName.Text);
    241                     isExit = true;
    242                     br.Close();
    243                     bw.Close();
    244                     client.Close();
    245                 }
    246                 catch
    247                 {
    248                 }
    249             }
    250         }
    251 
    252         /// <summary>
    253         /// 在发送信息的文本框中按下【Enter】键触发的事件
    254         /// </summary>
    255         /// <param name="sender"></param>
    256         /// <param name="e"></param>
    257         private void txt_SendText_KeyPress(object sender, KeyPressEventArgs e)
    258         {
    259             if (e.KeyChar == (char)Keys.Return)
    260             {
    261                 //触发【发送】按钮的单击事件
    262                 btn_Send.PerformClick();
    263             }
    264         }
    265 
    266         private void btn_LoadOnlineUser_Click(object sender, EventArgs e)
    267         {
    268 
    269         }
    270 
    271 
    272     }
    273 }

     

    转载于:https://www.cnblogs.com/ddwk/p/8742954.html

    展开全文
  • 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.IO; 7 8 namespace SyncChatServer ...1...
    
    
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Net.Sockets;
     6 using System.IO;
     7 
     8 namespace SyncChatServer
     9 {
    10     class User
    11     {
    12         public TcpClient client { get; private set; }
    13         public BinaryReader br { get; private set; }
    14         public BinaryWriter bw { get; private set; }
    15         public string userName { get; set; }
    16 
    17         public User(TcpClient client)
    18         {
    19             this.client = client;
    20             NetworkStream networkStream = client.GetStream();
    21             br = new BinaryReader(networkStream);
    22             bw = new BinaryWriter(networkStream);
    23         }
    24 
    25         public void Close()
    26         {
    27             br.Close();
    28             bw.Close();
    29             client.Close();
    30         }
    31 
    32     }
    33 }
    
    

     

      1 using System;
      2 using System.Collections.Generic;
      3 using System.ComponentModel;
      4 using System.Data;
      5 using System.Drawing;
      6 using System.Linq;
      7 using System.Text;
      8 using System.Windows.Forms;
      9 using System.Net;
     10 using System.Net.Sockets;
     11 using System.Threading;
     12 using System.IO;
     13 
     14 namespace SyncChatServer
     15 {
     16     public partial class MainForm : Form
     17     {
     18         /// <summary>
     19         /// 保存连接的所有用户
     20         /// </summary>
     21         private List<User> userList = new List<User>();
     22 
     23         /// <summary>
     24         /// 服务器IP地址
     25         /// </summary>;
     26         private string ServerIP;
     27 
     28         /// <summary>
     29         /// 监听端口
     30         /// </summary>
     31         private int port;
     32         private TcpListener myListener;
     33 
     34         /// <summary>
     35         /// 是否正常退出所有接收线程
     36         /// </summary>
     37         bool isNormalExit = false;
     38 
     39         public MainForm()
     40         {
     41             InitializeComponent();
     42             lst_State.HorizontalScrollbar = true;
     43             btn_Stop.Enabled = false;
     44             SetServerIPAndPort();
     45         }
     46 
     47         /// <summary>
     48         /// 根据当前程序目录的文本文件‘ServerIPAndPort.txt’内容来设定IP和端口
     49         /// 格式:127.0.0.1:8885
     50         /// </summary>
     51         private void SetServerIPAndPort()
     52         {
     53             FileStream fs = new FileStream("ServerIPAndPort.txt", FileMode.Open);
     54             StreamReader sr = new StreamReader(fs);
     55             string IPAndPort = sr.ReadLine();
     56             ServerIP = IPAndPort.Split(':')[0]; //设定IP
     57             port = int.Parse(IPAndPort.Split(':')[1]); //设定端口
     58             sr.Close();
     59             fs.Close();
     60         }
     61 
     62 
     63         /// <summary>
     64         /// 开始监听
     65         /// </summary>
     66         /// <param name="sender"></param>
     67         /// <param name="e"></param>
     68         private void btn_Start_Click(object sender, EventArgs e)
     69         {
     70             myListener = new TcpListener(IPAddress.Parse(ServerIP), port);
     71             myListener.Start();
     72             AddItemToListBox(string.Format("开始在{0}:{1}监听客户连接", ServerIP, port));
     73             //创建一个线程监客户端连接请求
     74             Thread myThread = new Thread(ListenClientConnect);
     75             myThread.Start();
     76             btn_Start.Enabled = false;
     77             btn_Stop.Enabled = true;
     78         }
     79 
     80         /// <summary>
     81         /// 接收客户端连接
     82         /// </summary>
     83         private void ListenClientConnect()
     84         {
     85             TcpClient newClient = null;
     86             while (true)
     87             {
     88                 try
     89                 {
     90                     newClient = myListener.AcceptTcpClient();
     91                 }
     92                 catch
     93                 {
     94                     //当单击‘停止监听’或者退出此窗体时 AcceptTcpClient() 会产生异常
     95                     //因此可以利用此异常退出循环
     96                     break;
     97                 }
     98                 //每接收一个客户端连接,就创建一个对应的线程循环接收该客户端发来的信息;
     99                 User user = new User(newClient);
    100                 Thread threadReceive = new Thread(ReceiveData);
    101                 threadReceive.Start(user);
    102                 userList.Add(user);
    103                 AddItemToListBox(string.Format("[{0}]进入", newClient.Client.RemoteEndPoint));
    104                 AddItemToListBox(string.Format("当前连接用户数:{0}", userList.Count));
    105             }
    106 
    107         }
    108 
    109         /// <summary>
    110         /// 处理接收的客户端信息
    111         /// </summary>
    112         /// <param name="userState">客户端信息</param>
    113         private void ReceiveData(object userState)
    114         {
    115             User user = (User)userState;
    116             TcpClient client = user.client;
    117             while (isNormalExit == false)
    118             {
    119                 string receiveString = null;
    120                 try
    121                 {
    122                     //从网络流中读出字符串,此方法会自动判断字符串长度前缀
    123                     receiveString = user.br.ReadString();
    124                 }
    125                 catch (Exception)
    126                 {
    127                     if (isNormalExit == false)
    128                     {
    129                         AddItemToListBox(string.Format("与[{0}]失去联系,已终止接收该用户信息", client.Client.RemoteEndPoint));
    130                         RemoveUser(user);
    131                     }
    132                     break;
    133                 }
    134                 AddItemToListBox(string.Format("来自[{0}]:{1}",user.client.Client.RemoteEndPoint,receiveString));
    135                 string[] splitString = receiveString.Split(',');
    136                 switch(splitString[0])
    137                 {
    138                     case "Login":
    139                         user.userName = splitString[1];
    140                         SendToAllClient(user,receiveString);
    141                         break;
    142                     case "Logout":
    143                         SendToAllClient(user,receiveString);
    144                         RemoveUser(user);
    145                         return;
    146                     case "Talk":
    147                         string talkString = receiveString.Substring(splitString[0].Length + splitString[1].Length + 2);
    148                         AddItemToListBox(string.Format("{0}对{1}说:{2}",user.userName,splitString[1],talkString));
    149                         SendToClient(user,"talk," + user.userName + "," + talkString);
    150                         foreach(User target in userList)
    151                         {
    152                             if(target.userName == splitString[1] && user.userName != splitString[1])
    153                             {
    154                                 SendToClient(target,"talk," + user.userName + "," + talkString);
    155                                 break;
    156                             }
    157                         }
    158                         break;
    159                     default:
    160                         AddItemToListBox("什么意思啊:" + receiveString);
    161                         break;
    162                 }
    163             }
    164         }
    165 
    166         /// <summary>
    167         /// 发送消息给所有客户
    168         /// </summary>
    169         /// <param name="user">指定发给哪个用户</param>
    170         /// <param name="message">信息内容</param>
    171         private void SendToAllClient(User user, string message)
    172         {
    173             string command = message.Split(',')[0].ToLower();
    174             if (command == "login")
    175             {
    176                 //获取所有客户端在线信息到当前登录用户
    177                 for (int i = 0; i < userList.Count; i++)
    178                 {
    179                     SendToClient(user, "login," + userList[i].userName);
    180                 }
    181                 //把自己上线,发送给所有客户端
    182                 for (int i = 0; i < userList.Count; i++)
    183                 {
    184                     if (user.userName != userList[i].userName)
    185                     {
    186                         SendToClient(userList[i], "login," + user.userName);
    187                     }
    188                 }
    189             }
    190             else if(command == "logout")
    191             {
    192                 for (int i = 0; i < userList.Count; i++)
    193                 {
    194                     if (userList[i].userName != user.userName)
    195                     {
    196                         SendToClient(userList[i], message);
    197                     }
    198                 }
    199             }
    200         }
    201 
    202         /// <summary>
    203         /// 发送 message 给 user
    204         /// </summary>
    205         /// <param name="user">指定发给哪个用户</param>
    206         /// <param name="message">信息内容</param>
    207         private void SendToClient(User user, string message)
    208         {
    209             try
    210             {
    211                 //将字符串写入网络流,此方法会自动附加字符串长度前缀
    212                 user.bw.Write(message);
    213                 user.bw.Flush();
    214                 AddItemToListBox(string.Format("向[{0}]发送:{1}", user.userName, message));
    215             }
    216             catch
    217             {
    218                 AddItemToListBox(string.Format("向[{0}]发送信息失败",user.userName));
    219             }
    220         }
    221 
    222         /// <summary>
    223         /// 移除用户
    224         /// </summary>
    225         /// <param name="user">指定要移除的用户</param>
    226         private void RemoveUser(User user)
    227         {
    228             userList.Remove(user);
    229             user.Close();
    230             AddItemToListBox(string.Format("当前连接用户数:{0}",userList.Count));
    231         }
    232 
    233         private delegate void AddItemToListBoxDelegate(string str);
    234         /// <summary>
    235         /// 在ListBox中追加状态信息
    236         /// </summary>
    237         /// <param name="str">要追加的信息</param>
    238         private void AddItemToListBox(string str)
    239         {
    240             if (lst_State.InvokeRequired)
    241             {
    242                 AddItemToListBoxDelegate d = AddItemToListBox;
    243                 lst_State.Invoke(d, str);
    244             }
    245             else
    246             {
    247                 lst_State.Items.Add(str);
    248                 lst_State.SelectedIndex = lst_State.Items.Count - 1;
    249                 lst_State.ClearSelected();
    250             }
    251         }
    252 
    253         /// <summary>
    254         /// 停止监听
    255         /// </summary>
    256         /// <param name="sender"></param>
    257         /// <param name="e"></param>
    258         private void btn_Stop_Click(object sender, EventArgs e)
    259         {
    260             AddItemToListBox("开始停止服务,并依次使用户退出!");
    261             isNormalExit = true;
    262             for (int i = userList.Count - 1; i >= 0; i--)
    263             {
    264                 RemoveUser(userList[i]);
    265             }
    266             //通过停止监听让 myListener.AcceptTcpClient() 产生异常退出监听线程
    267             myListener.Stop();
    268             btn_Start.Enabled = true;
    269             btn_Stop.Enabled = false;
    270         }
    271 
    272         /// <summary>
    273         /// 关闭窗口时触发的事件
    274         /// </summary>
    275         /// <param name="sender"></param>
    276         /// <param name="e"></param>
    277         private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    278         {
    279             if (myListener != null)
    280                 btn_Stop.PerformClick();    //引发 btn_Stop 的Click事件
    281         }
    282     }
    283 }

     

    转载于:https://www.cnblogs.com/ddwk/p/8742978.html

    展开全文
  • c# 桌面软件, 文字检索处理,带几十万字词数据库,0.1秒以下检索速度优化,递归算法控件状态保存和载入。图片添加删除移动缩放处理。自定义控件添加删除移动等使用。用一个xml当数据库文件。提供源代码。
  • C#编写的EMS系统软件

    2017-10-17 19:59:26
    涉及到C#多个知识点很数据库知识,很不错的资料,大家可以下载学习。
  • 使用C#编写的汉字转拼音软件,包含整个项目的源代码,亲测可用,能够实现输入汉字后,输出对应拼音的功能,注释详细。
  • c#编写的画图软件

    2012-08-03 10:12:24
    一款简单的画图工具,实现了新建,保存,打开功能,可以画圆画矩形画直线,遗憾的是没能实现截图
  • C#写的简易局域网聊天软件,可以传送文件。
  • c#编写的四则运算软件,下载运行一下就可以喽
  • 软件将server与client和为一体。 使用方法:先打开此软件,点击host建立主机(端口自动随机配置好),在局域网的另外一台电脑上打开此软件,选择slave,填入host的IP地址与端口号,点击连接测试,测试成功后就可以...
  • C#编写Calendar

    2012-05-24 17:05:36
    C#编写Calendar,桌面办公软件,日历可以记载每天的工作事情,C#语言编写
  • C#编写的 发送邮件的小软件 支持大部分主流的邮箱

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,452
精华内容 1,380
关键字:

c#编写软件

c# 订阅