2011-07-30 13 views
0

我有我的(多线程)服务器这个奇怪的问题,当我得到超过500名玩家同时连接时,PrinterWriter需要超过100秒以上(2分钟),(),有时完成的flush()或打印。PrintWriter verry slow flush()和print()。多线程和套接字。

下面是代码:

public static void send(Player p, String packet) 
{ 
    PrintWriter out = p.get_out(); 
    if(out != null && !packet.equals("") && !packet.equals(""+(char)0x00)) 
    { 
     packet = Crypter.toUtf(packet); 
     out.print((packet)+(char)0x00); 
     out.flush(); 
    } 
} 

的PrintWriter的是这样的:

_in = new BufferedReader(new InputStreamReader(_socket.getInputStream())); 
_out = new PrintWriter(_socket.getOutputStream()); 

如果我添加同步到send()方法的关键字,整个服务器开始落后于每2秒,如果我不这样做,那么一些随机球员无缘无故开始落后。

任何人有什么想法?这是从哪里来的?我该怎么办?

+0

由于您无法控制客户端,因此您必须假设任何数量的客户端可能会停止阅读或速度缓慢。发生这种情况时,你必须考虑如何处理这个问题。如果您的客户正在以足够快的速度读取数据,您应该能够在10毫秒内刷新到500个连接。即缓冲器总是有空闲空间。你不能让一个慢的客户放慢每一个客户的速度。 –

回答

1

打印作家缠绕在插座的输出流,所以我要去猜测,说套接字输出缓冲区已满,所以写/冲洗通话将被阻塞,直到缓冲区有足够的空间来容纳消息正在发送。如果数据正在被写入到它更快

该套接字发送缓冲区可能变满比它可以被发送到客户端(或比客户端可以接收它更快)。

编辑:

附:如果您遇到可伸缩性问题,可能是因为使用java.io(每个套接字需要一个线程)而不是java.nio(在这种情况下,单个线程可以检测并执行那些具有待处理数据的套接字的操作) 。 nio旨在支持必须扩展到大量连接的应用程序,但编程模型更加困难。

+0

也许你是对的。我的默认缓冲区大小是:128 000 IN/49 152 OUT。够了吗?多少钱就够了? – Reacen

+0

这并不是关于缓冲区大小,而是关于您写入套接字的速率,以及客户端可以传输和接收数据的速率。如果第一个速率大于第二个速率,那么主叫方总是会阻止/等待。在这种情况下,您可能会尝试发送太多的数据太快;降低更新速率或正在发送的数据量可能会有所帮助。 – JimN

0

的原因是,你send()方法是静态的,所以写任何套接字的所有线程正在syncrhonized包含类对象上。使其成为非静态的,那么只有写入同一个套接字的线程才会被同步。

+0

尽管该方法看起来像一种不共享任何资源的实用程序方法,因此不需要进行同步。如果多个调用者可能同时操作一个Player实例,那么调用者可能应该负责在实用程序方法之外同步某些对象,如Player实例本身。 – JimN

+0

你是对的!谢谢!代码太大,我不得不改变很多东西,但是谢谢。如果它只是一个线程问题,我希望它能解决这个问题。 – Reacen