Java Socket Server滞后于两个客户端
作者:互联网
我是StackOverflow的新手lol,但我一直依赖这个网站.我有一个关于我创建的Java套接字服务器的问题.在连接(客户端和服务器)时,我的应用程序为该客户端创建一个线程.这是一款MMORPG游戏服务器……至少是尝试过.有一个玩家,它不会落后那么糟糕.然而,有两个,它开始显示一些滞后…
如果我在其中一个客户端上左右 – 左右 – 发送垃圾邮件,并且正常地与另一个客户端一起移动,则另一个会感到毛病.我希望得到一些助手,因为我已经花了一个半星期的时间来纠结=)这是我寻求帮助的时候了.
代码很简单:
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(),我刚刚创建了一个简单的方法,将锥形短路到字节(通过字节向客户端发送缓冲包).例如,我有大约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();
从我所看到的……我的“垃圾邮件左/右”结束似乎缺少服务器发送的数据包.
解决方法:
问题解决了. =)setTcpNoDelay true做了伎俩.关于我说我丢失数据包的部分,我实际上没有.这两条消息合并在一起作为一条消息传入.我的程序只读取前几个字节而忽略了其余的字节.不得不在前面放一个字节来表示消息的大小.一旦到位,我设置了一个while循环来读取它直到它不能再读取. =)感谢大家帮助我.我的第一篇文章,这是一次盛大的经历.
标签:java,multithreading,sockets,2d-games 来源: https://codeday.me/bug/20190711/1432600.html