我是新手,但我已经依赖这个网站一段时间了。我有一个关于我创建的Java套接字服务器的问题。在连接时(客户端和服务器),我的应用会为该客户端创建一个线程。这是一个MMORPG游戏服务器……至少试图成为一个。对于一个玩家来说,它不会卡顿得那么厉害。然而,当有两个玩家时,它开始出现一些卡顿。
如果我在其中一个客户端上连续按下左右箭头,并在另一个客户端上正常移动,那么另一个客户端会感觉到有点卡顿。我希望能得到一些帮助,因为我已经纠缠了一个多星期了。现在是时候寻求帮助了。这里是简单的代码:
这就是一切的开始!在Player对象上,看起来像这样:
看下面的结构,有什么想法为什么我会出现延迟吗?
编辑:我认为将setTcpNoDelay设置为true可以大大改善它。当我在我的端口狂按左/右键时,似乎还存在延迟...屏幕上的其他玩家看起来很卡顿。
从我看到的情况来看,我的“向左/向右闪烁”端好像少了服务器发送的数据包。
如果我在其中一个客户端上连续按下左右箭头,并在另一个客户端上正常移动,那么另一个客户端会感觉到有点卡顿。我希望能得到一些帮助,因为我已经纠缠了一个多星期了。现在是时候寻求帮助了。这里是简单的代码:
public static void main(String[] args) throws IOException{
serverRooms.put(roomNumber, new Room());
try {
System.out.println("Starting Server...");
serverSocket = new ServerSocket(9595, 20);
System.out.println("Server Started");
while(run){
Socket socket = serverSocket.accept(); // Check if we have a connection, otherwise wait
Player player = new Player(playerCount++, socket, roomNumber);
new Thread(player).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
这就是一切的开始!在Player对象上,看起来像这样:
public void run() {
while(playerIsConnected) {
try {
int msgid = input.readUnsignedByte();
messageHandler(this, msgid);
} catch (IOException e) {
System.err.println("Player have signed off");
playerIsConnected = false;
}
}
// If Player leaves, close socket, and end thread
try {
socket.close();
} catch (IOException e) {
System.out.println("We got an error while closing a socket on player " + pid + ".");
}
}
messageHandler是来自Final Static类的静态方法。它是一个全局方法,每个线程都可以调用(这可能是导致延迟的原因吗?)。
public final class MessageControl {
public static void messageHandler(Player player, int msgid) throws IOException{
DataInputStream input = player.getInputStream();
switch (msgid) {
case 10:
byte hspd = (byte) Math.signum(input.readByte());
byte vspd = (byte) Math.signum(input.readByte());
byte dir = input.readByte();
updatePlayerPosition(player);
byte spd = (byte) (hspd != 0 && vspd != 0 ? player.spd-1 : player.spd);
// Prepare packet and send to clients
ByteBuffer buffer = ByteBuffer.allocate(11);
buffer.put((byte) 10);
buffer.put(shortToByte_U16(player.pid));
buffer.put(shortToByte_U16(player.x));
buffer.put(shortToByte_U16(player.y));
buffer.put((byte)(hspd*spd));
buffer.put((byte)(vspd*spd));
buffer.put((byte)(dir));
sendPacketToAllClients(player, buffer, true);
// Update Player info
player.hspd = (byte) hspd;
player.vspd = (byte) vspd;
player.dir = dir;
player.lastUpdate = System.currentTimeMillis();
break;
}
private static void sendPacketToAllClients(Player player, ByteBuffer buffer, boolean includeMe){
for (Player otherPlayer : player.room.getPlayersInRoom()){
if (otherPlayer.pid != player.pid || includeMe){
sendPacketToClient(otherPlayer, buffer);
}
}
}
}
关于shortToByte_U16(),我刚刚创建了一个简单的方法,将short类型转换为byte类型(通过字节将缓冲区数据包发送给客户端)。例如,我有大约5个这样的转换,其中包括无符号u16的转换。
public static byte[] shortToByte_16(int x){
short s = (short) x;
byte[] ret = new byte[2];
ret[0] = (byte)(s & 0xff);
ret[1] = (byte)((s >> 8) & 0xff);
return ret;
}
看下面的结构,有什么想法为什么我会出现延迟吗?
编辑:我认为将setTcpNoDelay设置为true可以大大改善它。当我在我的端口狂按左/右键时,似乎还存在延迟...屏幕上的其他玩家看起来很卡顿。
Socket socket = serverSocket.accept(); // Check if we have a connection, otherwise wait
socket.setTcpNoDelay(true); // This helped a lot!!!
Player player = new Player(playerCount++, socket, roomNumber);
new Thread(player).start();
从我看到的情况来看,我的“向左/向右闪烁”端好像少了服务器发送的数据包。