具有多个客户端的套接字服务器,向许多客户端发送消息而不会损害活力

时间:2010-04-19 01:08:03

标签: java multithreading oop design-patterns

我有一个小型套接字服务器,我需要根据不同的条件从客户端到客户端分发各种消息。

但是我认为我当前代码中的生动性有一个小问题,我的方法有什么问题:

public class CuClient extends Thread
{

Socket socket = null;
ObjectOutputStream out;
ObjectInputStream in;
CuGroup group;

public CuClient(Socket s, CuGroup g)
{
    this.socket = s;
    this.group = g;
    out = new ObjectOutputStream(this.socket.getOutputStream());
    out.flush();
    in = new ObjectInputStream(this.socket.getInputStream());
}

@Override
public void run()
{
    String cmd = "";
    try {
        while (!cmd.equals("client shutdown")) {
            cmd = (String) in.readObject();
            this.group.broadcastToGroup(this, cmd);
        }
        out.close();
        in.close();
        socket.close();
    } catch (Exception e) {
        System.out.println(this.getName());
        e.printStackTrace();
    }
}

public void sendToClient(String msg)
{
    try {
        this.out.writeObject(msg);
        this.out.flush();
    } catch (IOException ex) {
    }
}

我的CuGroup:

public class CuGroup
{
private Vector<CuClient> clients = new Vector<CuClient>();


public void addClient(CuClient c)
{
    this.clients.add(c);
}

void broadcastToGroup(CuClient clientName, String cmd)
{
    Iterator it = this.clients.iterator();
    while (it.hasNext()) {
        CuClient cu = (CuClient)it.next();
        cu.sendToClient(cmd);
    }
}
}

我的主要班级:

public class SmallServer
{
public static final Vector<CuClient> clients = new Vector<CuClient>(10);
public static boolean serverRunning = true;
private ServerSocket serverSocket;
private CuGroup group = new CuGroup();

public void body()
{
    try
    {
        this.serverSocket = new ServerSocket(1337, 20);
        System.out.println("Waiting for clients\n");
        do
        {
            Socket s = this.serverSocket.accept();
            CuClient t = new CuClient(s,group);
            System.out.println("SERVER: " + s.getInetAddress() + " is connected!\n");
            t.start();
        } while (this.serverRunning);
    } catch (IOException ex)
    {
        ex.printStackTrace();
    }
}

public static void main(String[] args)
{
    System.out.println("Server");
    SmallServer server = new SmallServer();
    server.body();
}
}

考虑具有更多组的示例,可能是组的集合。如果它们都在一个对象上同步,我认为我的服务器不会很快。

我有一种模式或某种东西可以帮助我的活力吗?

2 个答案:

答案 0 :(得分:1)

正确性方面的最大缺陷是ObjectOutputStream不是一个线程安全的类。通过从各种线程调用sendToClient,您已经暴露于一个大的竞争条件,其中两个外发消息相互混合。

两个简单但效率低下的解决方案:1)同步sendToClient,2)为每个从BlockingQueue读取的客户端创建发送方线程,并更改sendToClient以添加到该队列。前者是浪费,因为单个高延迟客户端会使其他客户陷入瓶颈。后者是浪费的,因为它需要双倍的线程。正如@spender所说,asynch IO对于这段代码确实会更好,但它对代码来说肯定不那么直接。

答案 1 :(得分:0)

看起来您需要对异步IO(即不阻塞的IO)进行一些研究。每个客户端使用一个线程永远不会很好地扩展。

这个问题有几个答案可能会指出你正确的方向:

Asynchronous IO in Java?

相关问题