C# 和 SUMO - 与套接字的通信不成功
C# and SUMO - Unsuccessful communication with sockets
我正在尝试使用 C# 脚本与交通模拟器 SUMO 进行通信。启动 SUMO 监听端口并等待客户端连接。
连接成功。然后,我尝试做一个模拟步骤,发送相应的命令,然后接收响应。
但是,当我尝试接收响应时,我的程序在尝试执行此行时被阻止:
int i = paramDataInputStream.ReadInt32() - 4;
其中 paramDataInputStream
是 BinaryReader
。我知道这个方法 ReadInt32 正在阻塞系统,因为没有数据可供读取,这使我得出以下结论:
- 命令发送不正确。
- 套接字定义不明确
- 因为我拿了一些 Java code 并试图翻译它,
可能有一些错误
在SUMO's webpage中他们定义了通信协议。是说以下内容:
A TCP message acts as container for a list of commands or results.
Therefore, each TCP message consists of a small header that gives the
overall message size and a set of commands that are put behind it. The
length and identifier of each command is placed in front of the
command. A scheme of this container is depicted below:
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 | |
+--------------------------------------+ /
在"Simulation Step command"的情况下,标识符为0x02,内容只是一个对应时间步长的整数(点击here了解更多详情)。
在提供更多关于我发送消息的方式的代码之前,我对我定义套接字的方式有一个疑问,这可能就是原因。我在尝试从 Java 转换为 C# 时查看了 Internet,我发现了这个:
this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
而在Java源代码中,套接字仅定义如下:
this.socket = new Socket();
由于通信协议看起来并不完全像 TCP(在我的例子中 header 是总长度之一,而 TCP 的 header 相当复杂),也许我定义的方式插座不正确。
如果 comments/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 的 ACK,但时间步长没有改善,我没有收到服务器的答复。
您指定的是 application layer 协议。它是在 TCP 之上定义的。因此,您仍然使用套接字与 send/receive 数据进行通信,并使用 SUMO 规范了解如何 encode/decode 您发送的消息。
我发现了错误。错误不在代码中,而是在我启动 SUMO 的方式中。 "steplength" 没有初始化,因此,时间步长已经完成,但模拟时间并没有因此改变。
我正在尝试使用 C# 脚本与交通模拟器 SUMO 进行通信。启动 SUMO 监听端口并等待客户端连接。 连接成功。然后,我尝试做一个模拟步骤,发送相应的命令,然后接收响应。
但是,当我尝试接收响应时,我的程序在尝试执行此行时被阻止:
int i = paramDataInputStream.ReadInt32() - 4;
其中 paramDataInputStream
是 BinaryReader
。我知道这个方法 ReadInt32 正在阻塞系统,因为没有数据可供读取,这使我得出以下结论:
- 命令发送不正确。
- 套接字定义不明确
- 因为我拿了一些 Java code 并试图翻译它, 可能有一些错误
在SUMO's webpage中他们定义了通信协议。是说以下内容:
A TCP message acts as container for a list of commands or results. Therefore, each TCP message consists of a small header that gives the overall message size and a set of commands that are put behind it. The length and identifier of each command is placed in front of the command. A scheme of this container is depicted below:
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 | |
+--------------------------------------+ /
在"Simulation Step command"的情况下,标识符为0x02,内容只是一个对应时间步长的整数(点击here了解更多详情)。
在提供更多关于我发送消息的方式的代码之前,我对我定义套接字的方式有一个疑问,这可能就是原因。我在尝试从 Java 转换为 C# 时查看了 Internet,我发现了这个:
this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
而在Java源代码中,套接字仅定义如下:
this.socket = new Socket();
由于通信协议看起来并不完全像 TCP(在我的例子中 header 是总长度之一,而 TCP 的 header 相当复杂),也许我定义的方式插座不正确。
如果 comments/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 的 ACK,但时间步长没有改善,我没有收到服务器的答复。
您指定的是 application layer 协议。它是在 TCP 之上定义的。因此,您仍然使用套接字与 send/receive 数据进行通信,并使用 SUMO 规范了解如何 encode/decode 您发送的消息。
我发现了错误。错误不在代码中,而是在我启动 SUMO 的方式中。 "steplength" 没有初始化,因此,时间步长已经完成,但模拟时间并没有因此改变。