分享

C#管道通讯2

 姬风 2012-06-20

3.客户端代码

在实验一的基础上,客户端使用两个线程,一个线程中实例一个客户端,使用管道通信向客户端发送数据(数据结构转为string类型);另一个线程中接收服务器端管道中的数据,再将string转为定义的数据结构。

[csharp] view plaincopy
  1. //定义要传递的数据结构  
  2.        PassStruct myPass = new PassStruct(  
  3.            new int[,]{  
  4.                     {1,2,3,4,5,6,7,8,9},  
  5.                     {1,2,3,4,5,6,7,8,9},  
  6.                     {1,2,3,4,5,6,7,8,9},  
  7.                     {1,2,3,4,5,6,7,8,9},  
  8.                     {1,2,3,4,5,6,7,8,9},  
  9.                     {1,2,3,4,5,6,7,8,9},  
  10.                     {1,2,3,4,5,6,7,8,9},  
  11.                     {1,2,3,4,5,6,7,8,9},  
  12.                      {1,2,3,4,5,6,7,8,9}  
  13.                 },   
  14.                 new byte[16] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7 },  
  15.                 "Authror:小魏");  
  16. private void 打开aToolStripMenuItem_Click(object sender, EventArgs e)  
  17.         {  
  18.             A = new Thread(new ThreadStart(exePa));  
  19.             A.IsBackground = true;   
  20.             A.Start();  
  21.         }  
  22.   
  23.         //声明一个委托,用以解决控件绑定到特定线程抛出的InvalidOperationException异常  
  24.         delegate void setRtbHandler(string s);  
  25.         private void setRtb(string s)  
  26.         {  
  27.             tabPage2.Controls[0].Text += s;  
  28.         }  
  29.   
  30.         /// <summary>  
  31.         /// 进程Pa  
  32.         /// </summary>  
  33.         private void exePa()  
  34.         {  
  35.             ////原本用作测试的  
  36.             //this.tabPage2.Controls[0].Text = "aaa";  
  37.             info += "线程A(写入线程)打开\n";  
  38.             try{  
  39.                 //这里第一个参数是我的计算机名  
  40.                 NamedPipeClientStream pipeClientA =  
  41.                 new NamedPipeClientStream("WEI-THINKPAD""testpipe",      
  42.                 PipeDirection.InOut, PipeOptions.None,  
  43.                 TokenImpersonationLevel.Impersonation);  
  44.                 StreamWriter sw = new StreamWriter(pipeClientA);  
  45.                 StreamReader sr = new StreamReader(pipeClientA);  
  46.                 pipeClientA.Connect();  
  47.                 sw.AutoFlush = true;  
  48.                   
  49.                 //确认服务器连接  
  50.                 if (sr.ReadLine() == "My Server!")  
  51.                 {  
  52.                     //向管道中写入数据(先转化为字符串)  
  53.                     toWrite = StructToString(myPass);  
  54.                     sw.Write(toWrite);  
  55.                 }  
  56.                 else  
  57.                 {  
  58.                     info +="Server could not be verified.\n";  
  59.                 }  
  60.                 //关闭客户端  
  61.                 pipeClientA.Close();  
  62.             }  
  63.             catch(Exception ex)  
  64.             {  
  65.                 MessageBox.Show(ex.Message);  
  66.             }  
  67.         }  
  68.   
  69.        /// <summary>  
  70.        /// 关闭A  
  71.        /// </summary>  
  72.        /// <param name="sender"></param>  
  73.        /// <param name="e"></param>  
  74.         private void 关闭AToolStripMenuItem_Click(object sender, EventArgs e)  
  75.         {  
  76.             if (A.IsAlive)  
  77.             {  
  78.                 info += "线程A(写入线程)已关闭\n";  
  79.                 A.Abort();  
  80.             }  
  81.         }  
  82.   
  83.         private void 打开aToolStripMenuItem1_Click(object sender, EventArgs e)  
  84.         {  
  85.             B = new Thread(new ThreadStart(exePb));  
  86.             B.IsBackground = true;  
  87.             B.Start();  
  88.         }  
  89.   
  90.         /// <summary>  
  91.         /// 线程B  
  92.         /// </summary>  
  93.         private void exePb()  
  94.         {  
  95.             info += "线程B(读出线程)打开\n";  
  96.             try  
  97.             {  
  98.                 NamedPipeClientStream pipeClientB =  
  99.                 new NamedPipeClientStream("WEI-THINKPAD""testpipe",  
  100.                 PipeDirection.InOut, PipeOptions.None,  
  101.                 TokenImpersonationLevel.Impersonation);  
  102.                 StreamWriter sw = new StreamWriter(pipeClientB);  
  103.                 StreamReader sr = new StreamReader(pipeClientB);  
  104.                 pipeClientB.Connect();  
  105.                 sw.AutoFlush = true;  
  106.                 if (sr.ReadLine() == "My Server!")  
  107.                 {  
  108.   
  109.                     PassStruct getPass = StringToStruct(toWrite);  
  110.                     string structToShow="";  
  111.                       
  112.                     //将读到的数据结构以一定的格式显示到屏幕上  
  113.                     for (int i = 0; i < 9; i++)  
  114.                 {  
  115.                         for (int j = 0; j < 9; j++)  
  116.                         {  
  117.                             structToShow += getPass.arrayInt[i, j].ToString() + " ";  
  118.                         }  
  119.                         structToShow += "\n";  
  120.                     }  
  121.                     for (int k = 0; k < 16; k++)  
  122.                         structToShow += getPass.arrayByte[k].ToString() + " ";  
  123.                     structToShow += "\n";  
  124.                     structToShow += getPass.ss;  
  125.                     structToShow += "\n";  
  126.   
  127.                     info += structToShow;  
  128.                 }  
  129.                 else  
  130.                 {  
  131.                     info += "Server could not be verified.\n";  
  132.                 }  
  133.                 pipeClientB.Close();  
  134.             }  
  135.             catch (Exception ex)  
  136.             {  
  137.                 MessageBox.Show(ex.Message);  
  138.             }  
  139.   
  140.         }  
  141.   
  142.         /// <summary>  
  143.         ///关系线程B  
  144.         /// </summary>  
  145.         /// <param name="sender"></param>  
  146.         /// <param name="e"></param>  
  147.         private void 关?闭à?ToolStripMenuItem1_Click(object sender, EventArgs e)  
  148.         {  
  149.             if (B.IsAlive)  
  150.             {  
  151.                 B.Abort();  
  152.                 A.Abort();  
  153.                 info += "线程B(读出线程)已关闭\n";  
  154.                 this.tabPage2.Controls[0].Text = info;  
  155.             }  
  156.         }  

4.数据结构与string相互转化的函数

[csharp] view plaincopy
  1. //数据结构转为字符串(所有的数字变为字符串,用“,”隔开)  
  2.         public string StructToString(PassStruct ps)  
  3.         {  
  4.             string s = "";  
  5.             for (int i = 0; i < 9; i++)  
  6.                 for (int j = 0; j < 9; j++)  
  7.                     s =s+(ps.arrayInt[i, j]).ToString() + ",";  
  8.             for (int k = 0; k < 16; k++)  
  9.                 s = s + (ps.arrayByte[k]).ToString() + ",";  
  10.             s = s + ps.ss;  
  11.             return s;  
  12.         }  
  13.   
  14.         //将string转为定义的数据结构  
  15.         public PassStruct StringToStruct(string s)  
  16.         {  
  17.             int[,] x = new int[9, 9];  
  18.             for (int i = 0; i < 9; i++)  
  19.             {  
  20.                 for (int j = 0; j < 9; j++)  
  21.                 {  
  22.                     int p = s.IndexOf(',');// 通过‘,’找到分割  
  23.                     string tmp = s.Substring(0, p);// 截取‘,’之前的部分转为int  
  24.                     x[i, j] = int.Parse(tmp);  
  25.                     s = s.Remove(0, p + 1);// 通过Remove移除已转为int的部分  
  26.                 }  
  27.             }  
  28.             //同样的方法得到byte部分  
  29.             byte[] y = new byte[16];  
  30.             for (int k = 0; k < 16; k++)  
  31.             {  
  32.                 int p = s.IndexOf(',');  
  33.                 string tmp = s.Substring(0, p);  
  34.                 y[k] = byte.Parse(tmp);  
  35.                 s = s.Remove(0, p + 1);  
  36.             }  
  37.             //剩下的部分为结构中字符串的部分  
  38.             PassStruct getPass = new PassStruct(x, y, s);  
  39.             return getPass;  
  40.         }  

5.实验中遇到的问题

实验的大部分地方都是用try catch来处理异常,catch中通过MessageBox显示可以很快看到错误问题。实验中遇到:


网上查阅了一些资料,了解信号灯也是进程间通信的一种方式。“信号灯与其它进程间通信方式有所不同,它主要用于进程间同步。通常所说的系统V信号灯实际上是一个信号灯的集合,可用于多种共享资源的进程间同步。每个信号灯都有一个值,可以用来表示当前该信号灯代表的共享资源可用(available)数量,如果一个进程要申请共享资源,那么就从信号灯值中减去要申请的数目,如果当前没有足够的可用资源,进程可以睡眠等待,也可以立即返回。”(http://www.cnblogs.com/thinkingworld/articles/1861739.html

不少人遇到过这个故障(数据库中或硬盘读盘),但最终还是没有读懂,不知道自己为什么会遇到这个问题。猜测可能还是不同线程向窗口写入东西(改变空间属性)引起的问题。于是将输出的信息改为一次性输出,暂时没有再出现问题。(具体见代码中注释)

实验结果:

服务器端输出截图:

 

客户端截图:



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多