为什么我的基本tcp聊天应用程序仅在通过nodejs中的ECONNRESET结束连接时才起作用?

时间:2018-03-12 12:24:40

标签: c# node.js sockets tcp

我有一个奇怪的场景,我不知道如何解决它。

我在nodejs中有一个简单的tcp聊天服务器,我的客户端当前使用的是本地C#,最终将转移到Unity。我有自己的网络库,可以创建TCP连接并处理消息等,在某些情况下工作正常,直到断开连接。

服务器在EC2实例上运行,我在PC上加载两个窗口来测试多个连接。当我关闭窗口时,我在nodejs服务器控制台

中收到此错误
Error: read ECONNRESET
    at exports._errnoException (util.js:870:11)
    at TCP.onread (net.js:544:26)

哪个好,因为这是它工作的场景。我猜这只是意味着连接突然关闭(关闭窗口)。

但是当我指示套接字关闭时会出现问题。

我正在将我的客户端移植到Unity,当关闭客户端时,它不会产生此ECONNRESET错误,并且连接永远不会突然关闭(就像我期望的那样),所以在这种情况下我必须手动关闭客户端上的连接,这会导致不同的错误。

Error: This socket has been ended by the other party
    at Socket.writeAfterFIN [as write] (net.js:268:12)
    at /opt/chat/chat.js:32:10
    at Array.forEach (native)
    at broadcast (/opt/chat/chat.js:31:10)
    at Socket.<anonymous> (/opt/chat/chat.js:26:2)
    at emitNone (events.js:72:20)
    at Socket.emit (events.js:166:7)
    at endReadableNT (_stream_readable.js:905:12)
    at nextTickCallbackWith2Args (node.js:441:9)
    at process._tickCallback (node.js:355:17)

当我在服务器上收到此错误时,其他连接的客户端可以继续向服务器发送消息,但是他们无法从服务器接收消息。

我的nodejs服务器是从github这里提取的:

https://gist.github.com/creationix/707146

// Load the TCP Library
net = require('net');

// Keep track of the chat clients
var clients = [];

// Start a TCP Server
net.createServer(function (socket) {

  // Identify this client
  socket.name = socket.remoteAddress + ":" + socket.remotePort 

  // Put this new client in the list
  clients.push(socket);

  // Send a nice welcome message and announce
  socket.write("Welcome " + socket.name + "\n");
  broadcast(socket.name + " joined the chat\n", socket);

  // Handle incoming messages from clients.
  socket.on('data', function (data) {
    broadcast(socket.name + "> " + data, socket);
  });

  // Remove the client from the list when it leaves
  socket.on('end', function () {
    clients.splice(clients.indexOf(socket), 1);
    broadcast(socket.name + " left the chat.\n");
  });

  // Send a message to all clients
  function broadcast(message, sender) {
    clients.forEach(function (client) {
      // Don't want to send it to sender
      if (client === sender) return;
      client.write(message);
    });
    // Log it to the server output too
    process.stdout.write(message)
  }

}).listen(5000);

// Put a friendly message on the terminal of the server.
console.log("Chat server running at port 5000\n");

方案

假设我们左侧有客户A ,右侧有客户B

enter image description here

在初次连接时,他们都可以聊天。

CLIENT B 希望断开连接,代码通过终止套接字强制断开连接。 nodejs服务器收到错误“此套接字已被另一方结束”并广播此播放器已断开与客户端A

enter image description here

客户端A 希望继续通信,无论是否有人连接。 客户端A 继续输入和发送消息,但是一旦 CLIENT B 断开连接,就不会收到消息。但是,消息确实正在发送到服务器。

客户端A 没有收到自己的消息。

客户B 希望重新连接以继续聊天并执行此操作。 客户端A 发送消息'hello' 客户B 发送消息'hello'

enter image description here

客户端B 正在看到这两条消息,并且正在进行正常聊天,但是客户端A 没有看到任何消息,并且卡在试图读取的阻止呼叫上数据

仅当我强行关闭套接字时,它才会收到ECONNRESET错误时完全正常。我该如何复制此错误或修复我的问题?

修改

我设法重现了ECONNRESET错误,现在它可以正常工作,但它仍然无法解释为什么它不能与其他错误一起使用。

C#Close中的方法GetStream().CloseTcpClient不足以正常关闭连接。相反,我必须直接访问套接字并关闭它。

直接关闭套接字可以在本机C#应用程序中使用,但不能在Unity中使用。

要在Unity中复制此错误,我必须使用 Shutdown(SocketShutdown.Receive);

0 个答案:

没有答案