[英]How to send a simple UInt over TCP to Client with Node and C#
I am using a Node server to send a simple 16 bit Int to my client in Unity.我正在使用 Node 服务器向 Unity 中的客户端发送一个简单的 16 位 Int。 The Unity client has a C# client script to connect to the node server and read the value.
Unity 客户端有一个 C# 客户端脚本连接到节点服务器并读取值。
The code I am using passes a String so I am converting the Int to a String and then back again on the client.我正在使用的代码传递一个字符串,因此我将 Int 转换为字符串,然后再次返回客户端。 I would rather just pass the value as a UInt16... firstly, is this more efficient?
我宁愿只是将值作为 UInt16 传递......首先,这更有效吗? and how do I do pass it and convert it on the client?
以及如何传递它并在客户端上转换它?
Here is the node code:这是节点代码:
server.on('connection', function(socket) {
console.log('A new connection has been established.');
// Now that a TCP connection has been established, the server can send data to
// the client by writing to its socket.
if (sensor != null){
sensor.on("change", value => {
socket.write(value.toString());
});
}
// The server can also receive data from the client by reading from its socket.
socket.on('data', function(chunk) {
console.log(`Data received from client: ${chunk.toString()}`);
});
// When the client requests to end the TCP connection with the server, the server
// ends the connection.
socket.on('end', function() {
console.log('Closing connection with the client');
});
// Don't forget to catch error, for your own sake.
socket.on('error', function(err) {
console.log(`Error: ${err}`);
});
});
and this is the C#
code in Unity:这是 Unity 中的
C#
代码:
socketConnection = new TcpClient("localhost", 8080);
Byte[] bytes = new Byte[1024];
while (true)
{
using (NetworkStream stream = socketConnection.GetStream())
{
int length;
// Read incoming stream into byte array
while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)
{
var incomingData = new byte[length];
//Debug.Log(incomingData.GetValue(0));
//int value = Convert.ToUInt16(incomingData);
//Debug.Log(value);
Array.Copy(bytes, 0, incomingData, 0, length);
// Convert byte array to string message.
string serverMessage = Encoding.ASCII.GetString(incomingData);
int value = Int16.Parse(serverMessage);
Debug.Log(value);
}
}
}
I need to do some refactoring but generally, this works to pass a String
.我需要做一些重构,但一般来说,这可以传递一个
String
。 Passing the UInt16
has not worked.通过
UInt16
无效。 Any help greatly appreciated.非常感谢任何帮助。
I would rather just pass the value as a UInt16... firstly, is this more efficient?
我宁愿只是将值作为 UInt16 传递......首先,这更有效吗?
It is - but there are many advantages to using text-based protocols instead of binary protocols: namely, it's MUCH easier to debug and inspect text-based protocols than binary protocols.确实如此 - 但是使用基于文本的协议而不是二进制协议有很多优点:也就是说,调试和检查基于文本的协议比二进制协议容易得多。 HTTP is text-based, for example (HTTP/2 is a binary protocol, but only because Google wanted to hyper-optimize it which makes sense at their scale, but for the vast majority of applications using a text-based protocol makes a lot more sense).
例如,HTTP 是基于文本的(HTTP/2是一种二进制协议,但这只是因为 Google 想要对其进行超优化,这在其规模上是有意义的,但是对于使用基于文本的协议的绝大多数应用程序来说更有意义)。
and how do I do pass it and convert it on the client?
以及如何传递它并在客户端上转换它?
With difficulty:有困难:
It's harder to work with specific numeric types in JavaScript because JavaScript has only the number
type which isn't even an integer type.在 JavaScript 中使用特定的数字类型更难,因为 JavaScript 只有
number
类型,甚至不是 integer 类型。 JavaScript [does have typed buffers][1] but that's an advanced topic. JavaScript [确实有类型缓冲区][1] 但这是一个高级主题。
When dealing with multi-byte binary integers you need to deal with "network-ordering" of multi-byte values, also known as endianness .在处理多字节二进制整数时,您需要处理多字节值的“网络排序”,也称为字节序。 Most C#.NET environments are "little-endian" but convention is to always use big-endian format on the wire .
大多数 C#.NET 环境都是“little-endian”,但惯例是始终在线路上使用 big-endian 格式。
TCP only sends packets when the system feels it's optimal (because there's a lot of overhead for each TCP packet), but by default sending individual 2-byte values won't actually be sent until the system has buffered up a lot of 2-byte values - otherwise you'll have to force-flush the network-stack. TCP 仅在系统认为最佳时发送数据包(因为每个 TCP 数据包有很多开销),但默认情况下,在系统缓冲大量 2 字节之前不会实际发送单独的 2 字节值values - 否则你将不得不强制刷新网络堆栈。 Note that using a text-based protocol has the same problem, but at least with a text-based protocol there's less conceptual wastage.
请注意,使用基于文本的协议有同样的问题,但至少使用基于文本的协议会减少概念上的浪费。
For sending single 16-bit integer values - you really are better-off sticking with a text protocol.对于发送单个 16 位 integer 值 - 你真的最好坚持使用文本协议。
...but if you insist: ...但如果你坚持:
server.on('connection', function(socket) {
console.log('A new connection has been established.');
if (sensor != null){
sensor.on("change", value => {
if( typeof value !== 'number' ) {
throw new Error( "value must be a number." );
}
if( value < 0 || value > 65535 || Math.floor( value ) !== value ) {
throw new Error( "value must be a 16-bit unsigned integer." );
}
const buffer = new Uint8Array( 2 );
const hi = ( value >> 8 ) & 0xFF;
const lo = ( value ) & 0xFF;
buffer.set( [ hi, lo ] ); // Big-Endian Order.
const didFlush = socket.write( buffer );
if( !didFlush ) console.log('Data did not send immediately.');
});
}
// [...]
});
TcpClient tc = new TcpClient("localhost", 8080); // A TcpClient is not a Socket. It encapsulates a Socket.
Byte[] buffer = new Byte[4096]; // Use 4K as a network buffer size.
while (true)
{
using( NetworkStream stream = tc.GetStream() )
{
Int32 read;
while( ( read = stream.Read( buffer, 0, buffer.Length ) ) != 0 )
{
if( read % 2 != 0 )
{
// TODO: Handle the case where a 16-bit value is half-sent.
continue;
}
// It is highly unlikely that each packet will contain only 2 bytes, instead it's more likely a sequence of 16-bit integers will be sent all-at-once, so we read each of them in 2-byte steps from the buffer:
for( Int32 idx = 0; idx < read; idx += 2 )
{
Byte hi = buffer[ idx + 0 ];
Byte lo = buffer[ idx + 1 ];
UInt16 value = ( hi << 8 ) | ( lo );
Debug.Log( value );
}
} // while
} // using
}
[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.