C# 如何使用Node和C通过TCP向客户端发送简单UInt#
我使用一个节点服务器向Unity中的客户端发送一个简单的16位Int。Unity客户端有一个C#客户端脚本,用于连接到节点服务器并读取值 我使用的代码传递一个字符串,因此我将Int转换为字符串,然后在客户端上再次转换。我宁愿将值作为UInt16传递。。。首先,这是否更有效率?我如何在客户机上传递和转换它 以下是节点代码:C# 如何使用Node和C通过TCP向客户端发送简单UInt#,c#,node.js,tcp,C#,Node.js,Tcp,我使用一个节点服务器向Unity中的客户端发送一个简单的16位Int。Unity客户端有一个C#客户端脚本,用于连接到节点服务器并读取值 我使用的代码传递一个字符串,因此我将Int转换为字符串,然后在客户端上再次转换。我宁愿将值作为UInt16传递。。。首先,这是否更有效率?我如何在客户机上传递和转换它 以下是节点代码: server.on('connection', function(socket) { console.log('A new connection has been es
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}`);
});
});
这是统一的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);
}
}
}
我需要进行一些重构,但一般来说,这可以传递一个字符串
。传递UInt16
无效。非常感谢您的帮助
我宁愿将值作为UInt16传递。。。首先,这是否更有效率
是的,但是使用基于文本的协议而不是二进制协议有很多优点:即,与二进制协议相比,调试和检查基于文本的协议要容易得多。例如,HTTP是基于文本的(HTTP/2是一种二进制协议,但这只是因为Google想对其进行超优化,这在他们的规模上是有意义的,但对于绝大多数使用基于文本的协议的应用程序来说,这更有意义)
我如何在客户机上传递和转换它
困难地:
- 在JavaScript中使用特定的数字类型比较困难,因为JavaScript只有
类型,甚至不是整数类型。JavaScript[确实有类型化缓冲区][1],但这是一个高级主题number
- 当处理多字节二进制整数时,需要处理多字节值的“网络顺序”,也称为endianness。大多数C#.NET环境都是“小端”的,但惯例是在线路上总是使用大端格式
- TCP只在系统认为它是最佳的时候发送数据包(因为每个TCP数据包都有很多开销),但是默认情况下,在系统缓冲了大量的2字节值之前,发送单个的2字节值实际上不会被发送,否则您将不得不强制刷新网络堆栈。请注意,使用基于文本的协议也有同样的问题,但至少对于基于文本的协议,概念上的浪费更少
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.');
});
}
// [...]
});
server.on('connection',函数(socket){
log('已建立新连接');
如果(传感器!=null){
传感器打开(“更改”,值=>{
如果(值的类型!=='number'){
抛出新错误(“值必须是数字”);
}
如果(值<0 | |值>65535 | |数学地板(值)!==值){
抛出新错误(“值必须是16位无符号整数。”);
}
const buffer=新的Uint8Array(2);
常量hi=(值>>8)&0xFF;
常量lo=(值)&0xFF;
set([hi,lo]);//大端顺序。
const didFlush=socket.write(缓冲区);
if(!didFlush)console.log('数据没有立即发送');
});
}
// [...]
});
TcpClient tc=newtcpclient(“localhost”,8080);//TCP客户端不是套接字。它封装了一个套接字。
字节[]缓冲区=新字节[4096];//使用4K作为网络缓冲区大小。
while(true)
{
使用(NetworkStream=tc.GetStream())
{
Int32读取;
while((read=stream.read(buffer,0,buffer.Length))!=0)
{
如果(读取%2!=0)
{
//TODO:处理16位值一半发送的情况。
持续
}
//每个数据包不太可能只包含2个字节,而是更可能一次发送16位整数序列,因此我们从缓冲区以2字节的步骤读取每个数据包:
对于(Int32 idx=0;idx UInt16值=(您好,您不需要输入数据
顺便说一句。显然,您需要使用缓冲区类和writeUInt16xx…在节点端发送文本,并期望它可以作为int16读取,这并不奇怪。这并不能回答如何send@Selvin我还没有写完我的答案。谢谢!知道我的问题为什么被记下来了吗?
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