我正在开发一款在GameMaker工作室中创建的多人游戏。我已经在游戏制造商中创建了一个服务器和一个客户端,它工作得很好,但游戏制造商服务器无法在任何虚拟机上运行,因为它必须使用DirectX。
所以我想用Java重写服务器,这将为我扩展这些选项。我看了很多教程,我只看到人们发送“字符串”作为消息,我想用字节替换。因为在我在GameMaker中创建的服务器中,我使用消息ID来标识每条消息应该引用的位置。这些是我读它的行:
buffer_seek(buffer, buffer_seek_start, 0);
var mid = buffer_read(buffer, buffer_u8);
switch(mid) {
case 0:
但在Java中,据我所知,只有一个输入流。我怎么能像下面的代码一样拆分该消息: (GameMaker的网络异步事件(服务器))
case network_type_data:
var buffer = ds_map_find_value(async_load, "buffer");
var socket = ds_map_find_value(async_load, "id");
buffer_seek(buffer, buffer_seek_start, 0);
var mid = buffer_read(buffer, buffer_u8);
switch(mid) {
case 0:
//let's updated the first information we can get whether the user is registering or loging in
//Reads what username was assigned to player
var username = buffer_read(buffer, buffer_string);
//Updates information of players
UpdatePlayerInfo("name", username, socket);
SendRoomList(1, socket);
break;
case 1: //player wants to create a server
//find the name of the player
show_debug_message("a player created a room");
if(Room_exists(socket) == false and PlayerInRoom(socket) == false) {
var Room = CreateRoom(socket, 2);
JoinRoom(socket, Room);
SendRoomList(1, socket);
}
break;
case 2: //player wants to join the server
var desired_room = buffer_read(buffer, buffer_u8);
if(PlayerInRoom(socket) == false) {
JoinRoom(socket, desired_room);
}
break;
}
}
答案 0 :(得分:1)
Java的ByteBuffer是一个很好的开始,能够从简单的流中获取String以外的项目。从本质上讲,你从TCP输入流中获取一大块字节到ByteBuffer实例中,你可以调用getInt(),getDouble()和其他类似的方法从中获取原始类型。
在这里,它的一些用法与问题中的脚本类似地安排。
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class JavaIo {
// number of bytes in a user name
private static final int SIZE_OF_USER_NAME = 30;
// number of bytes in the internal buffer
private static final int BUFFER_SIZE = 1024;
public void workWithConnection() {
final int portNumber = 12345; // TODO: read this from config file or command line arguments instead
try (
ServerSocket server = new ServerSocket(portNumber);
Socket connection = server.accept();
SocketChannel channel = connection.getChannel();
) {
final ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
channel.read(buffer); // fill buffer from the input stream
// since your buffer in GameMaker is unsigned, let's prevent all that signed to unsigned nonsense by doing a
// bitmask
final int mid = buffer.get() & 0x000000FF;
switch(mid) {
case 0:
// grab some bytes from the buffer and change them into a String
final byte[] usernameBytes = new byte[SIZE_OF_USER_NAME];
buffer.get(usernameBytes);
final String username = new String( usernameBytes, Charset.forName(StandardCharsets.UTF_8.name()));
// ...
break;
case 1:
// grab 4 bytes from the buffer and change it into an integer
final int roomId = buffer.getInt();
// ...
break;
default:
// ...
}
} catch(IOException ioe) {
// TODO: handle exception
}
}
}
参考文献:
Convert a byte array to integer in java and vice versa
http://www.ibm.com/developerworks/java/tutorials/j-nio/j-nio.html