繁体   English   中英

Java中的服务器程序,并传递对Socket对象的引用

[英]Server program in Java and passing a reference to a Socket object

我正在用Java写一个多线程程序,在这里我创建了一个单独的线程来处理每个新的客户端连接。 我有:

Socket s;


while(true)
{
    s = server.accept();
    ClientHandler ch = new ClientHandler(s);
    Thread servingThread = new Thread(ch);
    servingThread.start();
}

在ClientHandler线程中,我有:

public class ClientHandler implements Runnable
{
    private Socket s;

public ClientHandler(Socket _Socket, boolean _accepted, BaseStation _bs)
{
    this.s = _Socket;
}

如果在Java中我无法传递对象,而只能传递对其的引用,那么只要server接受新连接,这都不会对ClientHandler内的s实例造成问题吗? 它也不会在ClientHandler内部更改并破坏它吗? 如果是这样,正确的方法是什么?

请参阅Java是“按引用传递”还是“按值传递”? 解释。

将新的Socket实例传递给新的ClientHandler实例很好,因为每个ClientHandler都有自己的Socket更改本地变量s的值不会影响ClientHandler内部的Socket实例的副本。

这样的东西会导致一个问题:

ClientHandler ch = new ClientHandler(s);
Thread servingThread = new Thread(ch);
servingThread.start();

s.someMethod(); // close, read etc.

因为ch.ss都指向同一个基础Socket对象实例。

顺便说一句:在while循环中分离出一个新的线程可能是不好的,除非您确定这些线程将终止。 使用ThreadPool可能更好。

您的担心是正确的,因为Socket对象(与Java中的其他任何对象一样)都是通过引用传递的,因此有可能被不同的模块或不同的线程引用,从而导致不可预测的行为。

但是,如果您的程序没有问题。 原因是:每当服务器接受新连接时,它将创建一个新的 Socket对象,然后将其传递给ClientHandler实例。 因此,来自客户端的每个新连接都将由一个独立的ClientHandler实例提供服务,因此不必担心Socket对象的争用条件。 因此,您现在是安全的。

作为反例,如果您决定创建两个ClientHandler线程以从同一 Socket对象中读取,就像这样...

s = server.accept();
ClientHandler ch = new ClientHandler(s);
ClientHandler ch2 = new ClientHandler(s);
new Thread(ch).start();
new Thread(ch2).start();

......那么你可能会遇到麻烦因为有两个ClientHandler旨意得到相同的参照相同 Socket对象,如果都试图从同一个套接字读取他们将各获得只有一半的数据。 例如,如果您收到字符串"hello" ,则可能会以ch读取为"hel"ch2读取为"lo"或任何其他组合而结束。

这有点令人困惑,但是您的代码应该按所示工作。 Java首先通过值传递,然后通过引用传递。 IE浏览器,你不是在一个指针传递给你的“ Socket s ”,但“实际价值s ”当时你传递它。

为了简化事情并消除混乱,我只删除了您的“ Socket s; ”的前向声明,并使循环的第一行成为“ Socket s = server.accept(); ”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM