首页 新闻 会员 周边 捐助

求助,关于C#命名管道通信的,在客户端执行streamReader.ReadLine时会卡主,为什么?

0
[已解决问题] 解决于 2015-06-19 14:39

服务器代码:

using (NamedPipeServerStream ns = new NamedPipeServerStream("simple", PipeDirection.InOut,1))
            {
                Console.WriteLine(">> 服务器等待连接..");
                ns.WaitForConnection();
                Console.WriteLine(">> 服务器连接成功。");

                string msg = "1:服务器信息";
                byte[] data = Encoding.Default.GetBytes(msg);
                ns.Write(data, 0, data.Length);
                ns.Flush();

                ns.WaitForPipeDrain();
                Queue<byte> returnData = new Queue<byte>();
                int item;
                while ((item = ns.ReadByte()) != -1)
                {
                    returnData.Enqueue((byte)item);
                }
                data = returnData.ToArray();
                msg = Encoding.Default.GetString(data);
                Console.WriteLine(">> 客户端发送的信息" + msg);
            }
            Console.WriteLine(">> 服务器结束,按回车键关闭窗口");
            Console.ReadLine();

客户端代码:

using (NamedPipeClientStream nc = new NamedPipeClientStream(".", "simple", PipeDirection.InOut))
            {
                Console.WriteLine(">> 客户端等待连接");
                nc.Connect();
                Console.WriteLine(">> 客户端连接成功");
                string msg = "";
                Queue<byte> returnData = new Queue<byte>();
                int item;
                while ((item = nc.ReadByte()) != -1)
                {
                    returnData.Enqueue((byte)item);
                }
                byte[] data = returnData.ToArray();
                msg = Encoding.Default.GetString(data);
                Console.WriteLine(">> 服务器发送的信息:{0}", msg);
                msg = "1:客户端的信息";
                Console.WriteLine(">> 向服务器发送信息:" + msg);
                data = Encoding.Default.GetBytes(msg);
                nc.Write(data, 0, data.Length);
                nc.Flush();
                nc.WaitForPipeDrain();
            }
            Console.WriteLine(">> 客户端结束,按回车键关闭窗口");
            Console.ReadLine();

问题补充:

目前对此问题的发现是

1:双向的管道似乎不太适合使用StreamReader和StreamWriter来读写。因为当需要关闭StreamReader和StreamWriter时,后关闭的那个会因为管道已关闭而导致Close方法异常。

2:当服务器写输入,客户端读数据,没有其他读写操作时,且服务器不使用RunAsClient时,通信正常。当服务器有一次对客户端的写和对客户端的读,客户端对应的一次对服务器的读,一次对服务器的写实,服务器的读的位置与客户端的读的位置都会卡住进程,强制关闭服务器,客户端的读会继续,但,当然之后的写会因为管道的关闭而引发异常。

 

问题是:为什么会在服务器和客户端的读的位置卡住?

北在北方的主页 北在北方 | 初学一级 | 园豆:180
提问于:2015-06-18 16:12
< >
分享
最佳答案
1

两头堵住的原因是因为,没有可读的数据,使用NamedPipeClientStream或NamedPipeServerStream的Read读取是,并不会以返回-1值的形式报告数据已读完,当数据读完后,Read会堵塞,而不是返回-1,当客户端堵塞,服务器也会因为读取没有的数据而进入等待,从而导致堵塞。

北在北方 | 初学一级 |园豆:180 | 2015-06-19 14:38

写错了,应该是“..使用NamedPipeClientStream或NamedPipeServerStream的ReadByte读取...”

北在北方 | 园豆:180 (初学一级) | 2015-06-19 14:41
其他回答(2)
0

等待数据返回

Launcher | 园豆:45050 (高人七级) | 2015-06-18 16:15

可我服务器已经向管道写入数据了,为什么会卡主?应该能够读出来才对。

支持(0) 反对(0) 北在北方 | 园豆:180 (初学一级) | 2015-06-18 16:22

@北在北方: writer.Write(noteMsg) 后面加一句 writer.Flush()

支持(0) 反对(0) Launcher | 园豆:45050 (高人七级) | 2015-06-18 16:28

@Launcher: Flush也不起作用,我修改了代码,请再瞧瞧。

支持(0) 反对(0) 北在北方 | 园豆:180 (初学一级) | 2015-06-18 16:32

@北在北方: 客户端阻塞在 string strData = reader.ReadLine() 这一句时,服务端阻塞在哪一句上?

支持(0) 反对(0) Launcher | 园豆:45050 (高人七级) | 2015-06-18 16:41

@Launcher: 服务器一段堵在了string response = reader.ReadLine();这行,当我关闭服务器时,客户端读取到服务器首次发送的信息,然后报出管道已关闭的异常。为什么客户端会堵在ReadLine?服务器我都Flush了也没用吗,应该怎么做。

支持(0) 反对(0) 北在北方 | 园豆:180 (初学一级) | 2015-06-18 19:48

@北在北方: writer.WriteLine(noteMsg);  // 对应客户端  string strData = reader.ReadLine()
                 writer.Flush();

支持(0) 反对(0) Launcher | 园豆:45050 (高人七级) | 2015-06-19 09:11

@Launcher: 修改了问题,请再看看。

支持(0) 反对(0) 北在北方 | 园豆:180 (初学一级) | 2015-06-19 11:04
0

因为你写入的不是一行数据。

行结束符\r\n是很重要的。

傲慢与偏剑 | 园豆:381 (菜鸟二级) | 2015-06-18 16:26
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册