C#TCP读取欢迎消息并发送命令

时间:2016-04-13 08:59:47

标签: c# tcp

我在使用简单的TCP读/写应用程序时出现问题,我需要将命令写入设备/主机。通常我可以使用stream.Write()命令执行此操作,但是对于此特定设备,它似乎在发送任何命令之前发回初始欢迎消息(PJLINK 0)。我可以使用PuTTY发送命令,但在使用C#时,我认为我的连接正在关闭,然后才能完成命令。

所以我的问题是如何在没有TcpClient提前关闭连接的情况下调整下面的代码来接收欢迎消息,然后发回命令(我不需要阅读响应)?

非常感谢任何帮助。

                using (tcpClientA = new TcpClient())
                {
                    int portA = 4352;

                    if (!tcpClientA.BeginConnect("10.0.2.201", portA, null, null).AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1.0)))
                    {
                        throw new Exception("Failed to connect.");
                    }

                    while (tcpClientA.Connected)
                    {
                        using (streamA = tcpClientA.GetStream())
                        {
                            if (type == "raw")
                            {

                                // Buffer to store the response bytes.
                                byte[] writeBufferC = Encoding.ASCII.GetBytes("%1 INPT 32$0D"); //Command I need to send
                                byte[] readBufferC = new byte[tcpClientA.ReceiveBufferSize];
                                string fullServerReply = null;
                                using (var writer = new MemoryStream())
                                {
                                    do
                                    {
                                        int numberOfBytesRead = streamA.Read(readBufferC, 0, readBufferC.Length);
                                        if (numberOfBytesRead <= 0)
                                        {
                                            break;
                                        }
                                        writer.Write(writeBufferC, 0, writeBufferC.Length);
                                    } while (streamA.DataAvailable);
                                    fullServerReply = Encoding.UTF8.GetString(writer.ToArray());
                                    Console.WriteLine(fullServerReply.Trim());
                                }
                            }
                        }
                    }
                }

更新1 删除了BeginConnect和Async方法。

                using (tcpClientA = new TcpClient())
                {
                    int portA = 4352;

                    tcpClientA.Connect("10.0.2.201", portA);

                    while (tcpClientA.Connected)
                    {
                        using (streamA = tcpClientA.GetStream())
                        {
                            if (type == "raw")
                            {
                                byte[] readBufferC = new byte[tcpClientA.ReceiveBufferSize];
                                byte[] writeBufferC = Encoding.ASCII.GetBytes("%1 INPT 31$0D"); //Command I need to send

                                string fullServerReply = null;
                                using (var writer = new MemoryStream())
                                {
                                    do
                                    {
                                        streamA.Read(readBufferC, 0, readBufferC.Length); //First read
                                        writer.Write(writeBufferC, 0, writeBufferC.Length); //Send command
                                    } while (streamA.DataAvailable);
                                    fullServerReply = Encoding.UTF8.GetString(readBufferC.ToArray());
                                    Console.WriteLine(fullServerReply.Trim());
                                    tcpClientA.Close();
                                }
                            }
                        }
                    }
                }

1 个答案:

答案 0 :(得分:0)

DataAvailable未告诉您远程端将来会发送多少数据。它的使用几乎总是一个bug。在这里,它会让你提前随机退出循环。

读取,直到您拥有所需的所有字节或直到关闭流。

这是一个基于行的协议吗?实例化StreamReader并从流中绘制整行。

while (tcpClientA.Connected)什么也没做。即使它返回true,连接也可能在1纳秒之后丢失。无论如何,你的代码必须处理它。它应该是while (true)。这不是一个错误,它只是显示了弱的TCP理解,所以我指出它。

删除ReceiveBufferSize的所有用法。这个值意味着没有意义。而是使用固定的缓冲区大小。我发现4096可以很好地处理吞吐量不高的连接。

numberOfBytesRead <= 0应为==0。同样,不是一个错误,但你似乎并不清楚API的作用。这很危险。

在更新的代码中,您没有使用streamA.Read的返回值,这是一个错误。您已尝试通过修剪生成的\0字符来修复该错误。这只是治疗症状而不是真正的解决方法。

您需要一个套接字教程。这场大屠杀是因为你不依赖最佳实践。如果做得好,套接字读取循环实际上相当简单。此代码是可能出错的集合。