【问题标题】:How to duplicate a socket in Java (transfer to another thread)?如何在 Java 中复制一个套接字(转移到另一个线程)?
【发布时间】:2014-06-11 19:51:50
【问题描述】:

简短的历史:我有一个用 C# 编写的服务器应用程序(更准确地说是 telnet),它为每个连接的客户端打开一个新套接字和一个新线程,例如:

Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Socket clientSocket = newsock.Accept();
Thread _connection = new Thread();
....

用户打开连接后,系统会要求提供凭据(用户名和密码),然后可以对数据库执行一些操作。一个主要特点是,如果同一个用户尝试从不同的设备进行连接,连接总是会转移到新创建的线程,而另一个设备会断开连接,例如:

if (runningThread.UserID == Username.Value)
{
    SocketInformation _infoSock = runningThread.clientSocket.DuplicateAndClose(Process.GetCurrentProcess().Id);
    Socket _oldSocket = runningThread.clientSocket;
    newThread.clientSocket = new Socket(_infoSock); 
    _oldSocket.Close();
}

现在,我必须在 JAVA 中做同样的事情,最大的问题是:我该怎么做?到目前为止,我查看并发现,Java 中没有 DuplicateAndClose 的等价物!

编辑

在阅读了一些帖子和 cmets 之后,我认为最好解释一下我需要实现的目标:

假设在 t1 时刻,用户 John 正在使用设备 A 连接到服务器。服务器在套接字 1 上创建会话 1“通话”。稍后,在 t2 时刻,同一用户 John 正在使用设备 B(例如另一台计算机)连接到服务器。服务器创建在套接字 2 上“交谈”的会话 2,并要求 John 提供他的用户名和密码(在服务器创建匿名会话时不知道这些信息)。在 t3 时刻,当 John 将他的凭据提供给服务器时,会话不再是匿名的。

现在,服务器识别出 John 以及他已经有一个正在运行的会话这一事实,并且需要将现有会话“转移”到设备 B。由于工作会话不容易复制,因此进行转移的最佳方式是在 t3 时刻之后指示会话 1 与设备 B“交谈”。

在 C# 中,它通过复制套接字 2 并将其提供给会话 1 来工作,但在 Java 中我没有找到这样的功能。那么问题又来了:我如何在 Java 中做到这一点?

非常感谢任何有用的答案!

【问题讨论】:

  • 你有一个新的套接字,对吧?来自新设备的新连接?为什么不直接关闭现有的并用新的替换这个线程的 clientSocket?
  • 我真的不明白这个问题。你想“转移”什么? IO阻塞?国家?
  • 连接未“转移到新打开的设备”。新连接的设备有自己的线程和自己的连接。根据您的描述,前一个已关闭。就是这样。
  • "用新的替换这个线程的 clientSocket" - 我该怎么做?简单地编写 runningThread.clientSocket = newThread.clientSocket 不起作用,我需要以某种方式创建现有套接字的副本并将其提供给现有线程。

标签: java multithreading sockets transfer


【解决方案1】:

Java 中没有 DuplicateAndClose 的等价物

据此:http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.duplicateandclose(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1 DuplicateAndClose 处理使套接字跨进程可用的问题。这与跨线程执行不同。如果您在 Java 中(可能)使用多个线程而不是多个进程,则可以直接使用 Socket 对象 - 无论您在做什么,都不需要任何类型的 DuplicateAndClose 调用。

如果问题是您试图让来自同一个客户端的另一个连接表现得就像它已经基于另一个较早的连接登录一样 - 这实际上与套接字无关 - 那是您的内部应用程序状态的问题.制作已连接的客户端的同步地图并编写您需要的逻辑。

【讨论】:

  • 好吧,这让我回到我的问题。 “你可以直接使用 Socket 对象” - 我该怎么做?简单地写“runningThread.clientSocket = newThread.clientSocket”是行不通的,我需要以某种方式创建现有套接字的副本并将其提供给现有线程。
  • 那行不通怎么办?您绝对可以传递套接字对象,并从代码中的各个位置对其进行读写(尽管您需要注意不要同时写入两件事)。
  • 请看看我的编辑。是的,只要您不想更改它,您就可以绕过一个套接字并用它做任何您想做的事情。但是,当您想用另一个替换现有套接字时(例如在我的问题中,会话应该从一个设备更改为另一个设备)它不起作用。套接字不能简单地通过 a=b 操作进行更改。这就是 C# 中 DuplicateAndClose 方法的原因。
猜你喜欢
  • 2014-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-19
相关资源
最近更新 更多