C# 通过tcp协议向硬件发送命令,networkstream read 读取返回信息时卡死。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 通过tcp协议向硬件发送命令,networkstream read 读取返回信息时卡死。相关的知识,希望对你有一定的参考价值。

我有一个机器是可以通过PUTTY的TCP端口连接进去的。
只要输入IP和3002端口就可以进到命令行,输入命令。

每当我输入一个错误的信息的时候,它都会feedback一个错误的command。

我现在界面之类的全都做好了,我也通过TcpClient 和 networkstream 成功用write 传了命令进去。

问题是现在我试图用stream.read()来获取它返回的信息,每次运行到read这个方法的时候都会卡死。
(在网上查过,说是read方法会等待feedback的信息,没等到就一直等待。可是这个返回的信息是在我一开始传命令进去的时候就立刻传回来了)。
代码如下。

try

//通过Nerworkstream 来获得连接得到的流数据,再进行feedback的读写。
NetworkStream stream = tcpClientA.GetStream();
//输入命令的方法
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("(CLI 1 MicroTiles!)");
stream.Write(buffer, 0, buffer.Length);
stream.Flush();
/* ---------------------------以上为传命令-----------------------------*/

byte[] buffer2 = new byte[1024];
if (stream.CanRead) MessageBox.Show("可读");

/* ---------------------------以下为卡死语句-----------------------------*/
int BL = stream.Read(buffer2, 0, buffer2.Length);
/* --------------------------——————-卡死语句-----————------------------------*/
string meg2 = Encoding.ASCII.GetString(buffer2, 0, buffer2.Length);
MessageBox.Show(meg2);

我想实现的就是,我传了一个命令过去,然后同时在我的程序的UI上显示传回来的命令行。
求大神解决。
完美决绝的话本账号分数全送

邮箱:oo44@vip.qq.com

你使用的是telnet协议连接的设备

telnet并不是一个传输层协议 而是一个应用层协议 它是有一些格式上的规定的

比如 在交流前需要互相握手 会发送一些控制字符


你可以使用一些网络包监测工具(比如微软的network monitor)

或者自己创建一个模拟telnet服务器来研究这个包头:

void Main()

TcpListener server = new TcpListener(IPAddress.Loopback, 10010);
server.Start();

var client = server.AcceptSocket();
byte[] buffer = new byte[4096];
client.Send(new byte[1]);
while(true) 
int len = client.Receive(buffer);
if (len > 0)
Console.WriteLine("receive byte[0] 1", len, string.Join(",", buffer.Take(len)));
else
break;


server.Stop();

在我的机器上 使用putty连接这个服务器 收到的第一个串为

receive byte[21] 
255,251,31,255,251,32,255,251,24,255,251,39,255,253,1,255,251,3,255,253,3

你可以查看一些资料来了解这个串的含义

http://tools.ietf.org/html/rfc1572

http://en.wikipedia.org/wiki/Telnet

或者看看这篇blog

http://xu.xue.yi.blog.163.com/blog/static/957382482010582594065/


当进行初始化配置后 才可以进行telnet命令发送阶段。


=======================

一句话。。你连接后少发了个包头_(:з」∠)_

参考技术A 我建议你增加一个线程专门用来读取

首先创建一个method
void read()

int BL = stream.Read(buffer2, 0, buffer2.Length);
string meg2 = Encoding.ASCII.GetString(buffer2, 0, buffer2.Length);
MessageBox.Show(meg2);

然后在原来的地方将卡死语句替换成

Thread thr = new Thread(read);
thr.Start();

当然了,buffer2 这个你要放到外面去定义,并且是public类型的追问

void read(object st)

NetworkStream str1 = (NetworkStream)st;
int BL = str1.Read(buffer2, 0, buffer2.Length);
MessageBox.Show("2");

还是运行不到box2

参考技术B             TcpClient client = new TcpClient();

            try

            

                client.Connect(hostIp, port);

                NetworkStream ns = client.GetStream();

                ns.ReadTimeout = 3000;

                ns.WriteTimeout = 3000;

                byte[] bs = Encoding.Default.GetBytes(strInfo);

                ns.Write(bs, 0, bs.Length);

                byte[] bytes = new byte[1024];

                int length = ns.Read(bytes, 0, bytes.Length);

                string data = System.Text.Encoding.Default.GetString(bytes, 0, length);

                recData = data;

                client.Close();

                ns.Close();

            

            catch (Exception ex)

            

                client.Close();

                recData = ex.Message;

            

参考技术C 一般这个多线程问题。使用多线程处理。你使用单线程,就一直UI无响应。等待方法结束。
子线程不能控制UI。要想控制UI。需要UI做操作,允许子线程操作UI。上面代码messbox。show(“222”)在线程里是弹不出的。直接报错。
参考技术D 使用线程等待,增加超时处理

Java:通过 TCP 发送/接收数据并从 UDP 接收图像

【中文标题】Java:通过 TCP 发送/接收数据并从 UDP 接收图像【英文标题】:Java: send/receive data through TCP and receive image from UDP 【发布时间】:2021-12-14 01:22:12 【问题描述】:

我正在编写来自 C# 的代码,并试图在 java 中引用它。 基本上在第一步中,我通过 TCP 向 IP 摄像机发送和接收一些数据命令(这已完成),在第二步中,我必须通过 UDP 接收图像。问题出在第二步:从 UDP 接收图像。 我尝试了互联网上的所有代码,但没有一个工作。

原来的C#代码是这样的:

*C#中的服务器连接示例

    Socket _ServerUdp = null; 
    Socket _ServerTcpIp = null; 
    IPEndPoint _EndpointUdp = null; 
    TcpClient _ClientUdp; 
    /// <summary> 
    /// Connect the socket 
   /// <summary> 
    public bool Connect(string IpAddr) 
     
         if (!_VideoPortConnect(IpAddr, 8501)) 
                return false; 
        if (!_CommandPortConnect(IpAddr, 8500)) 
            return false; 
        return true; 
     
    /// <summary> 
    /// Udp Connect 
    /// </summary> 
    bool _VideoPortConnect(string IpAddr, int VideoPort) 
     
        try 
         
            _ServerUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 
            _EndpointUdp = new IPEndPoint(IPAddress.Parse(IpAddr), VideoPort); 
            _ClientUdp = new TcpClient(); 
            _ClientUdp.Connect(_EndpointUdp); 
            return true; 
         
        catch  return false;  
     

    /// <summary> 
    /// Tcp Ip Connect 
    /// </summary> 
    bool _CommandPortConnect(string IpAddr, int CommandPort) 
     
        _ServerTcpIp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
        IPEndPoint _RemoteEndPoint = new IPEndPoint(IPAddress.Parse(IpAddr), CommandPort); 
        _ServerTcpIp.ReceiveTimeout = 5000; 
        _ServerTcpIp.SendTimeout = 5000; 
        try 
         
            _ServerTcpIp.Connect(_RemoteEndPoint); 
            return true; 
         
        catch  return false;  
    ** 

发送命令和接收图像示例 该命令将通过 TCP/IP 发送。

byte[] DataReceived = 新字节[20000];

    /// <summary> 
    /// Send Command Bar Code Reader 
    /// </summary> 
    /// <returns></returns> 
    bool SendCommand() 
     
        byte[] _Send = new byte[3]; 
        _Send[0]= 20;    //CMD BAR CODE READER 
        _Send[1] = 2;    //EXT CMD GET DATA 
        _Send[2] = 2;    //SEND IMAGE 
        if (!SendEth(_Send, 3)) 
            return false; 
        int _Ndati = ReadEth(); 
        if (_Ndati == -1) 
            return false; 
        if (DataReceived[4] != 20) 
            return false; 
        GetImage(); 
     
    /// <summary> 
    /// Send Data 
    /// </summary> 
    /// <param name="_Val"></param> 
    /// <param name="_Len"></param> 
    bool SendEth(byte[] _Val, Int32 _Len) 
     
        try 
         
            byte[] _Send = new byte[_Len + 4]; 
            int _Value = _Len; 
            Array.Copy(_Val, 0, _Send, 4, _Len); 
            _Send[3] = (byte)_Value; 
            _Value <<= 8; 
            _Send[2] = (byte)_Value; 
            _Value <<= 8; 
            _Send[1] = (byte)_Value; 
            _Value <<= 8; 
            _Send[0] = (byte)_Value; 
            _ServerTcpIp.Send(_Send, _Len + 4, SocketFlags.None); 
         
        catch  return false;  
        return true; 
    
    /// <summary> 
    /// Read Data from Ethernet 
    /// </summary> 
    /// <param name="LenDati"></param> 
    /// <returns>array dati</returns> 
    internal int ReadEth() 
     
        int _Ndati; 
        try 
         
            _Ndati = _ServerTcpIp.Receive(DataReceived, SocketFlags.None); 
            DataPointer =0; 
            int _Len = GetInt(); 
            if(_Len!=_Ndati-4) 
             
                int _Diff = (_Ndati - 4) - _Len; 
                byte[] BuffRx = new byte[_Diff]; 
                int _NrDati = 0; 
                int _PuntRx = _Ndati; 
                while (_PuntRx < _Diff) 
                 
                    _NrDati = _ServerTcpIp.Receive(BuffRx, _Diff, SocketFlags.None); 
                    for (int n = 0; n < _NrDati; n++) 
                        DataReceived[_PuntRx++] = BuffRx[n]; 
                 
             
            return _Ndati; 
         

        catch  return -1;  
     

    /// <summary> 
    /// Get Image 
    /// </summary> 
    /// <returns></returns> 
    internal ImageSource GetImage() 
     
        //get image 
        NetworkStream _Stream = _ClientUdp.GetStream(); 
        byte[] _Data = (byte[])_Formatter.Deserialize(_Stream); 
        MemoryStream _ImgStream = new MemoryStream(_Data); 
        ImageSource _Image = BitmapFrame.Create(_ImgStream, BitmapCreateOptions.None, 
        BitmapCacheOption.OnLoad); 
        return _Image; 
     

我的 JAVA 代码:

公共类 TFinale

static byte[] DataReceived = new byte[20000];

public static void main(String[] args) throws Exception 
    String[] args8500 = new String[2];
    args8500[0] = "10.0.0.123";
    args8500[1] = "8500";
    int port8500 = Integer.parseInt(args8500[1]);

    String[] args8501 = new String[2];
    args8501[0] = "10.0.0.123";
    args8501[1] = "8501";
    int port8501 = Integer.parseInt(args8501[1]);

    Socket clientSocket8501 = TFinale.createSocket(args8501[0], port8501);
    if (clientSocket8501 == null) 
    System.err.println("Unable to create socket to " + args8501[0] + ":" + port8501 + ".");
    System.exit(1);
    
    Socket clientSocket8500 = TFinale.createSocket(args8500[0], port8500);

    if (clientSocket8500 == null) 
        System.err.println("Unable to create socket to " + args8500[0] + ":" + port8500 + ".");
        System.exit(1);
    

    byte[] _Send = new byte[3];
    _Send[0] = 22;    //CMD BAR CODE READER 
    _Send[1] = 2;    //EXT CMD GET DATA 
    _Send[2] = 2;    //SEND IMAGE
    int _Len1 = 3;
    byte[] SendEth1 = SendEth(_Send, _Len1);

    DataOutputStream serverOut = null;
    try 
        serverOut = new DataOutputStream(clientSocket8500.getOutputStream());
        serverOut.write(SendEth1, 0, 7);
        System.out.println("serverOut writed!");
     catch (IOException ex) 
        Logger.getLogger(TFinale.class.getName()).log(Level.SEVERE, null, ex);
    
    DataInputStream in = null;
    try 
        byte[] messageByte = new byte[1000];
        boolean end = false;
        String dataString = "";
        in = new DataInputStream(clientSocket8500.getInputStream());
        int bytesRead = 0;
        int f = 0;
        //System.out.println("Please type 8500 clientSocket......");
        for (f = 0; f < 7; f++) 
            messageByte[f] = in.readByte();
            System.out.println("messageByte 8500[" + f + "] " + messageByte[f]);
        
        ByteBuffer byteBuffer = ByteBuffer.wrap(messageByte, 0, f);
        int bytesToRead = byteBuffer.getShort();
        System.out.println("About to read " + bytesToRead + " octets");
     catch (IOException ex) 
        Logger.getLogger(TCPClient1.class.getName()).log(Level.SEVERE, null, ex);
     finally 
        try 
            in.close();
         catch (IOException ex) 
            Logger.getLogger(TCPClient1.class.getName()).log(Level.SEVERE, null, ex);
        
    
    timeDelay(1000);
    try 
        serverOut.close();
        System.out.println("serverOut closed!");
        in.close();
        System.out.println("in closed!");
        clientSocket8501.close();
        System.out.println("clientSocket8501 closed!");
        clientSocket8500.close();
        System.out.println("clientSocket8500 closed!");
     catch (IOException ex) 
        System.out.println("error:" + ex);
    



private static Socket createSocket(final String hostname, final int port) 
    try 
        Socket clientSocket = new Socket(hostname, port);
        System.out.println(hostname + ":" + port + " socket created!");
        return clientSocket;
     catch (UnknownHostException e) 
        System.err.println(" " + hostname + " cannot be resolved as a network host.");
        return null;
     catch (IOException e) 
        System.err
                .println("An exception occurred while communicating with the TCPServer: "
                        + e.getMessage());
        e.printStackTrace();
        return null;
    



private static void timeDelay(int i) 
    try 
        Thread.sleep(i);
     catch (InterruptedException e) 
    


private static byte[] SendEth(byte[] _Val, int _Len) 
    byte[] _Send = new byte[_Len + 4];
    int _Value = _Len;
    System.arraycopy(_Val, 0, _Send, 4, _Len);
    //Array.Copy(_Val, 0, _Send, 4, _Len); 
    _Send[3] = (byte) _Value;
    _Value <<= 8;
    _Send[2] = (byte) _Value;
    _Value <<= 8;
    _Send[1] = (byte) _Value;
    _Value <<= 8;
    _Send[0] = (byte) _Value;
    return _Send;




谢谢大家帮帮我!

【问题讨论】:

“它不起作用”对于任何人来说都没有足够的调试信息来提供帮助。发生什么了?这与您的预期有何不同? FWIW,这似乎会混淆问题:TcpClient _ClientUdp; 所以我们有一个以 UDP 命名的对象,它显然是用于 TCP 的类型。我们使用的是 TCP 还是 UDP?我的猜测是 TCP,理由是使用 UDP 处理大数据似乎有点傻。 我在互联网上尝试了许多代码显示来监听地址:8501 中的 udp,但在发送命令期间没有收到任何内容... 【参考方案1】:

@Federico111,您应该使用java.net.DatagramSocket 而不是Socket 来使用UDP。

【讨论】:

以上是关于C# 通过tcp协议向硬件发送命令,networkstream read 读取返回信息时卡死。的主要内容,如果未能解决你的问题,请参考以下文章

C# - 向 Telnet 服务器发送命令(纯文本)

HTTP协议

Java:通过 TCP 发送/接收数据并从 UDP 接收图像

C#实现断点续传

在 C 程序中使用 telnet

TCP,HTTP,socket,WEBSOCKET协议