【问题标题】:C# and SUMO - Unsuccessful communication with socketsC# 和 SUMO - 与套接字的通信不成功
【发布时间】:2018-07-20 20:25:44
【问题描述】:

我正在尝试使用 C# 脚本与交通模拟器 SUMO 进行通信。 SUMO 启动侦听端口并等待客户端连接。 连接成功。然后,我尝试做一个模拟步骤,发送相应的命令,然后接收响应。

但是,当我尝试接收响应时,我的程序在尝试执行此行时被阻止:

        int i = paramDataInputStream.ReadInt32() - 4;

其中paramDataInputStreamBinaryReader。我知道这种方法 ReadInt32 正在阻塞系统,因为没有可读取的数据,这使我得出以下结论:

  • 命令未正确发送。
  • 套接字定义不明确
  • 因为我拿了一些Java code 并试图翻译它, 可能有一些错误

SUMO's webpage 中,它们定义了通信协议。是这样说的:

TCP 消息充当命令或结果列表的容器。 因此,每个 TCP 消息都包含一个小的标头,该标头提供 整体消息大小和放在它后面的一组命令。这 每个命令的长度和标识符放在前面 命令。该容器的示意图如下:

 0                 7 8               15
+--------------------------------------+
| Message Length including this header |
+--------------------------------------+
|      (Message Length, continued)     |
+--------------------------------------+  \
|     Length        |    Identifier    |  |
+--------------------------------------+   > Command_0
|           Command_0 content          |  |
+--------------------------------------+  /
                   ...
+--------------------------------------+  \
|     Length        |    Identifier    |  |
+--------------------------------------+   > Command_n-1
|          Command_n-1 content         |  |
+--------------------------------------+  /

以“模拟步长命令”为例,标识为0x02,内容为时间步长对应的整数(点击here查看详情)。

在提供更多关于我发送消息的方式的代码之前,我对我定义套接字的方式有一个疑问,这可能是原因。我在尝试从 Java 转换为 C# 时查看了 Internet,发现:

this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

而在Java源代码中,socket只定义如下:

this.socket = new Socket();

由于通信协议看起来并不完全像 TCP(在我的情况下,标头是总长度之一,而 TCP 的标头要复杂得多),也许我定义套接字的方式不正确。

如果 cmets/answers 声明这不是问题,我将更新更多代码。

编辑

我花了一整天的时间进行试验,最后没有任何效果。最后,我做了一个非常简单的代码,对我来说似乎合乎逻辑,但也不起作用:

public static void step(NetworkStream bw, int j)
        {
            byte[] bytes = { 0, 0, 0, 10, 6, 2, 0, 0, 0, 0 };
            bw.Write(bytes, 0, bytes.Length);
            bw.Flush();
        }

    public static void Main(String[] argv)
    {

        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        socket.NoDelay = true;
        try
        {
            socket.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 60634));
        }
        catch (Exception localConnectException)
        {
            Console.WriteLine(localConnectException.StackTrace.ToString());
        }
        NetworkStream ns = new NetworkStream(socket);
        //BinaryWriter bw = new BinaryWriter(ns); (I tried with both, BinaryWriter and NetworkStream and the result was the same
        for (int i = 0; i < 100; i++)
        {
            step(ns,i);
        }
}

我发送的字节对应:4字节(1个整数)总长度(10字节),1字节命令长度(6字节),1字节命令标识符(0x02),以及命令内容的 4 个字节(1 个整数),在这种情况下为 0,因为我只想提前 1 个时间步。

我已经嗅探通信以检查字节是否正确发送,我什至从 SUMO 接收和确认,但时间步长没有改善,我没有收到服务器的回答。

【问题讨论】:

  • 能否分享您的 C++ 库以与 SUMO 进行通信?它可能对其他人有用:-)

标签: c# sockets tcp traffic-simulation


【解决方案1】:

您指定的是application layer 协议。它是在 TCP 之上定义的。因此您仍然使用套接字进行通信以发送/接收数据,并使用 SUMO 规范来了解如何编码/解码您发送的消息。

【讨论】:

  • 你的意思是“包括这个头的消息长度”、“长度”、“标识符”字段是TCP paquet里面的数据,对吧?那么,您会说错误可能出在我编写这些数据的方式上吗? (我会尽快更新我的帖子以获取更多详细信息)
  • 您在问题中拥有的所有字段都用于应用程序级协议(即 TCP 流中的数据)。请注意 TCP 是基于流的。应用程序消息可能会在多个 TCP 接收操作之间划分。
  • 我在网上看到了一些例子...创建TcpClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 有什么区别?
  • 长度字段包括自身和标识符字段。所以是1+1+4(整数)
【解决方案2】:

我发现了错误。错误不在代码中,而是在我启动 SUMO 的方式中。 “步长”未初始化,因此,时间步正在完成,但模拟时间并没有因此而改变。

【讨论】:

    猜你喜欢
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-26
    • 1970-01-01
    相关资源
    最近更新 更多