Java sockets游戏服务器调整
我正在制作一个多人游戏,我正在为服务器使用java套接字,服务器运行得很好,但我认为需要对解析/处理请求的方式进行一些调整Java sockets游戏服务器调整,java,sockets,Java,Sockets,我正在制作一个多人游戏,我正在为服务器使用java套接字,服务器运行得很好,但我认为需要对解析/处理请求的方式进行一些调整 我想知道是否有更好的方法来解析请求,而不是像我现在这样用(,)逗号分隔输入行 客户端和服务器之间发送的数据是否应该以某种方式加密?只是一个小的加密来混淆嗅探器眼睛上的请求。最好的方法是什么 关于线程安全,Collections.synchronizedList和synchronized块在迭代中可以吗?还是有更好/更干净的方法 最后,是否有java sockes库可以完成上
public class Servidor extends Thread {
private ServerSocket serverSocket;
public static boolean LISTENING = true;
private final List<Client> clients = Collections.synchronizedList(new ArrayList<Client>());
private final List<Game> games = Collections.synchronizedList(new ArrayList<Game>());
public Servidor() {
try {
serverSocket = new ServerSocket(SERVER_PORT);
} catch (IOException e) {
Log.add("error starting server: " + e);
}
}
@Override
public void run() {
// Wait for players to connect
while (LISTENING) {
try {
Client c = new Client(serverSocket.accept());
clients.add(c);
c.start();
} catch (IOException e) {}
}
}
class Client extends Thread {
private Socket socket;
private PrintWriter out;
private BufferedReader in;
private boolean loggedin;
private Player player;
private Game game;
public Cliente(Socket sock) {
socket = sock;
try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8")), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
} catch (IOException e) {
Log.add("error connecting to player!");
}
}
/* Send to this player */
public void send(String s) {
out.println(s);
}
/* Send to all players on the server */
public void boardcast(String s) {
synchronized (clients) {
for (Client c : clients) {
c.send(s);
}
}
}
/* Get player by ID */
private Player getPlayerByID(int playerID) {
synchronized (clients) {
for (Client c : clients) {
if (c.player != null) {
if (c.player.getID() == playerID) {
return c.player;
}
}
}
}
return null;
}
/* Split inputLine */
private String[] splitInput(String input, int argsNumber) {
String[] args = null;
try {
args = input.split(",", -1);
if (args.length != argsNumber) {
args = null;
}
} catch (Exception ex) {
Log.add("error splitting input");
} finally {
return args;
}
}
@Override
public void run() {
char cmd;
String inputLine, outputLine;
String[] args;
try {
loop:
while ((inputLine = in.readLine()) != null) {
// check if inputLine have 2 chars (CMD_TYPE:)
if (inputLine.length() < 2) {
kickPlayer();
break loop;
}
// get CMD
cmd = inputLine.charAt(0);
// remove (CMD_TYPE:) from inputLine
inputLine = inputLine.substring(2);
// check e player is logged (L:username,password)
if (!loggedin) {
// check if the input string have 2 arguments
if ((args = splitInput(inputLine, 2)) == null) {
kickPlayer();
break loop;
}else{
// ... TESTE LOGIN ON DATABASE ...
// set player data
player = new Player(query.getInt("player_id"), query.getString("username"), query.getInt("level"))
}
}else{
// Commands
switch (cmd) {
// P:CARD_ID,TARGET_ID eg:(P:5:3)
case CMD_PLAY:
// check if the input string have 2 arguments
if ((args = splitInput(inputLine, 2)) == null) {
kickPlayer();
break loop;
} else {
// ... VALIDATE OTHER PARAMETERS ...
// update game
game.addCard(args[0], args[0]);
// update players
boardcast(CMD_PLAY + ":" + player.getID+ "," + game.LastCard());
}
break;
// ... TEST OTHER COMMANDS ...
default:
Log.add("invalid command";
break loop;
}
}
}
} catch (IOException e) {
Log.add("connection lost";
} finally {
removeClient();
}
}
}
}
公共类服务扩展线程{
私有服务器套接字服务器套接字;
公共静态布尔侦听=true;
私有最终列表客户端=Collections.synchronizedList(新的ArrayList());
private final List games=Collections.synchronizedList(新的ArrayList());
公共服务商(){
试一试{
serverSocket=新的serverSocket(服务器端口);
}捕获(IOE异常){
添加(“启动服务器时出错:+e”);
}
}
@凌驾
公开募捐{
//等待玩家连接
边听{
试一试{
客户端c=新客户端(serverSocket.accept());
添加(c);
c、 start();
}捕获(IOE){}
}
}
类客户端扩展线程{
专用插座;
私人打印输出;
中的私有缓冲区读取器;
私有布尔loggedin;
私人玩家;
私人游戏;
公共客户(插座插座){
插座=插座;
试一试{
out=新的PrintWriter(新的BufferedWriter(新的OutputStreamWriter(socket.getOutputStream(),“UTF-8”)),true);
in=新的BufferedReader(新的InputStreamReader(socket.getInputStream(),“UTF-8”);
}捕获(IOE异常){
添加(“连接到播放器时出错!”);
}
}
/*发送给这个玩家*/
公共无效发送(字符串s){
out.println(s);
}
/*发送给服务器上的所有玩家*/
公共空白广播(字符串s){
已同步(客户端){
用于(客户c:客户){
c、 发送(s);
}
}
}
/*通过ID获取玩家*/
私人玩家GetPlayerByd(int-playerID){
已同步(客户端){
用于(客户c:客户){
如果(c.player!=null){
如果(c.player.getID()==playerID){
返回c.player;
}
}
}
}
返回null;
}
/*分割输入线*/
私有字符串[]拆分输入(字符串输入,int argsNumber){
字符串[]args=null;
试一试{
args=input.split(“,”,-1);
if(args.length!=argsNumber){
args=null;
}
}捕获(例外情况除外){
添加(“错误拆分输入”);
}最后{
返回args;
}
}
@凌驾
公开募捐{
char-cmd;
字符串输入行、输出行;
字符串[]args;
试一试{
循环:
而((inputLine=in.readLine())!=null){
//检查inputLine是否有2个字符(CMD\u类型:)
if(inputLine.length()<2){
kickPlayer();
断环;
}
//获取命令
cmd=inputLine.charAt(0);
//从输入行中删除(CMD_TYPE:)
inputLine=inputLine.子字符串(2);
//检查e播放器是否已登录(L:用户名、密码)
如果(!loggedin){
//检查输入字符串是否有2个参数
if((args=splitInput(inputLine,2))==null){
kickPlayer();
断环;
}否则{
//…测试登录数据库。。。
//设置播放器数据
player=新玩家(query.getInt(“玩家id”)、query.getString(“用户名”)、query.getInt(“级别”))
}
}否则{
//命令
开关(cmd){
//卡片ID,目标ID,例如:(P:5:3)
案例CMD_播放:
//检查输入字符串是否有2个参数
if((args=splitInput(inputLine,2))==null){
kickPlayer();
断环;
}否则{
//…验证其他参数。。。
//更新游戏
game.addCard(args[0],args[0]);
//更新玩家
boardcast(CMD_PLAY+“:“+player.getID+”,“+game.LastCard());
}
打破
//…测试其他命令。。。
违约
class ClientHandler
{
public void run()
{
while(isConnected())
messageRouter.handleMessage(getNextMessage());
}
}
interface MessageHandler
{
public boolean canHandle(Message m);
public void handleMessage(Message m);
}
class MessageRouter
{
private List<MessageHandler> handlers;
public void handleMessage(Message msg)
{
for(MessageHandler m : handlers)
{
if(m.canHandle(msg))
{
m.handle(msg);
return;
}
}
throw UnsupportedMessage();
}
}