네트워크 게임 서버 구조 연구(-) 프록시 서버의 간단한 실천

14817 단어 게임프레임Mina
인터넷 게임의 서버 프레임워크에서는 일반적으로 프록시 서버인 Proxy Server가 병렬 요청을 해결해야 한다.
현재 매우 간단한 프록시 서버를 실현했고 높은 병행 문제를 고려하지 않고 클라이언트, 프록시 서버와 게임 서버로부터의 간단한 통신만 실현했다.
클라이언트로부터 데이터를 전송하고 프록시 서버를 통해 게임 서버에 전송
게임 서버는 데이터를 프록시 서버에 반사하고 후자는 클라이언트에게 전달한다.
1. 클라이언트로부터 메시지 수신 담당
2. 서버에서 온 메시지 전달 담당
3. 클라이언트 연결 관리
클라이언트 연결 추가 및 제거
연결당 고유 태그
4. 서버 측 연결 관리
서버 id에 따라 서버 측 연결 관리하기;
현재 후속적으로 보완해야 할 부분이 매우 많다
1. 클라이언트 연결 관리,
프록시 서버가 클라이언트 연결을 받은 후 무작위clientid를 생성하여 ClientConnectIon을 구성하고 맵에 저장하여 사용할 수 있습니다
현재의clientid는 고정되어 있다
그래서 아직 여러 클라이언트 연결이 지원되지 않습니다.
물론 클라이언트의 끊긴 관리와 관련되어 맵에서 관련 연결을 제거합니다.
2. 프록시 서버의 병렬 능력 부족
후속 고려는 넷티나 미나로 해결한다
관건은 클라이언트가 연결되면 무작위clientid를 만들어서 맵에 저장해야 한다는 것이다
게임 서버에서 내려온 데이터로 정확한 클라이언트 연결을 찾을 수 있습니다
정확한 클라이언트에 데이터 전송
       netty4.x의 버전은 비교적 복잡한 것 같다. 3.5의 버전과 비교하면 새로운 종류와 인터페이스가 많아서 공부하는 데 시간이 좀 걸린다.
3. 패킷 포장
일반적으로 데이터 패키지의 봉인, 패키지 헤더 패키지
패키지 비교에는 TAG, bodylen, cmdtype 등이 포함된다
프록시 서버가 먼저 이렇게 하면 뒤에 있는 게임 서버에 대한 프레임워크가 더욱 중요하다.

package net.tuolian.main;

import net.tuolian.client.Client;
import net.tuolian.proxy.SocketProxy;
import net.tuolian.server.GameServer;

public class TestAll {
	
	public static void main(String[] args) {
		
		// boot game server
		new GameServer(8080);
		
		try {
			Thread.sleep(1000 * 3);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		// boot socket proxy
		SocketProxy proxy = new SocketProxy(8081);
		proxy.connectToLogicServer("localhost", 8080);
		
		try {
			Thread.sleep(1000 * 3);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// start client
		new Client("localhost", 8081).doTest();
	}
}

package net.tuolian.server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

public class GameServer implements Runnable{
	ServerSocket serverSocket 	= null;
	
	Logger logger = LogManager.getLogger(GameServer.class);

	public GameServer(int port)
	{
		try {
			serverSocket = new ServerSocket(port);
			
			logger.info("GameServer initialized");
			new Thread(this).start();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void run()
	{
		while(true)
		{
			try {
				Socket socket = serverSocket.accept();
				
				logger.info("client accepted: " + socket.getRemoteSocketAddress());
				new MyClient(socket);
				
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}
	public void doTest()
	{
		new Thread(this).start();
	}
	
	class MyClient extends Thread
	{
		DataInputStream dis 		= null;
		DataOutputStream dos	 	= null;
		
		public MyClient(Socket socket)
		{
			try {
				dis = new DataInputStream(socket.getInputStream());
				dos = new DataOutputStream(socket.getOutputStream());
				start();
				
				logger.info("MyClient init");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}			
		}
		
		public void run()
		{
			while(true)
			{
				byte[] tmp =new byte[1024];
				try {
					if(dis.available()>0)
					{
						dis.read(tmp);
						logger.info("recv data from proxy len: " + new String(tmp));
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
//				int cmd = 1;
				try {
					dos.write("this is echo from gameserver: ".getBytes());
					dos.flush();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		}
	}

}

package net.tuolian.proxy;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Random;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

public class SocketProxy implements Runnable{

	Logger logger = LogManager.getLogger(SocketProxy.class);
	ServerSocket sSocket = null;

	public SocketProxy(int port)
	{
		logger.info("SocketProxy init");
		try {
			sSocket = new ServerSocket(port);	
			
			new Thread(this).start();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}
	
	public void run()
	{
		while(true)
		{
			Socket client = null;
			try {
				client = sSocket.accept();
				if(client!=null)
				{
					logger.info("accept client ");

					// new clientconn
					int clientId = new Random().nextInt();
					ClientConnection clientConn = new ClientConnection(this, clientId,client);
					addClientConn(clientConn, 1);
					
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public void connectToLogicServer(String ip, int port)
	{
		logger.info("connectToLogicServer");
		Socket socket;
		try {
			socket = new Socket(ip, port);
			
			ServerConnection serverConn =new ServerConnection(this, 1, socket);
			addServerConn(serverConn, 1);
			
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	private HashMap<Integer,ClientConnection> clientConns = new HashMap<Integer, ClientConnection>();
	private HashMap<Integer,ServerConnection> serverConns = new HashMap<Integer, ServerConnection>();

	public void addClientConn(ClientConnection clientConn, int clientId) {
		// TODO Auto-generated method stub
		clientConns.put(clientId, clientConn);
	}
	
	public ClientConnection getClientConn(int clientId)
	{
		return clientConns.get(clientId);
	}
	
	public void removeClientConn(int clientId)
	{
		clientConns.remove(clientId);
	}
	
	public void addServerConn(ServerConnection serverConn, int serverid) {
		// TODO Auto-generated method stub
		serverConns.put(serverid, serverConn);
	}
	
	public ServerConnection getServerConn(int serverid)
	{
		return serverConns.get(serverid);
	}
	
	public void removeServerConn(int serverId)
	{
		serverConns.remove(serverId);
	}
}

package net.tuolian.proxy;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

public class ClientConnection implements Runnable {
	
	Logger logger = LogManager.getLogger(ClientConnection.class);

	SocketProxy proxy = null;
	int clientId = 0;
	Socket client = null;
	DataInputStream dis = null;
	DataOutputStream dos = null;

	public ClientConnection(SocketProxy proxy, int clientId, Socket socket) {
		logger.info("ClientConnection init");
		this.proxy = proxy;
		this.clientId = clientId;
		this.client = socket;
		
		try {
			dis = new DataInputStream(socket.getInputStream());
			dos = new DataOutputStream(socket.getOutputStream());
			new Thread(this).start();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void run()
	{
		while(true)
		{
			logger.info("run" );

			try {
				
				byte[] rawData = new byte[1024];
				while(dis.available()>0)
				{
					logger.info("recv client data: " );

					dis.read(rawData);
					String msg = new String(rawData);
					logger.info(msg);

					int serverid = 1;
					ServerConnection severConn = proxy.getServerConn(serverid);
					if(severConn!=null)
					{
						severConn.sendData(rawData);
					}
				}
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public void sendDataBack(byte[] data)
	{
		logger.info(new String(data));

		try {
			dos.write(data);
			dos.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

package net.tuolian.proxy;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

public class ServerConnection implements Runnable {

	Logger logger = LogManager.getLogger(ServerConnection.class);
	SocketProxy proxy = null;
	int serverId = 0;
	Socket client = null;
	DataInputStream dis = null;
	DataOutputStream dos = null;

	public ServerConnection(SocketProxy proxy, int serverId, Socket socket) {
		// TODO Auto-generated constructor stub
		logger.info("ServerConnection init");
		this.proxy = proxy;
		this.serverId = serverId;
		this.client = socket;
		
		try {
			dis = new DataInputStream(socket.getInputStream());
			dos = new DataOutputStream(socket.getOutputStream());
			
			new Thread(this).start();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void run()
	{
		while(true)
		{
			try {
				
				byte[] rawData = new byte[1024];
				while(dis.available()>0)
				{
					dis.read(rawData);
					
					logger.info(new String(rawData));
					// send to serverId;

					int clientId = 1;
					ClientConnection clientConn = proxy.getClientConn(clientId);
					if(clientConn!=null)
					{
						clientConn.sendDataBack(rawData);
					}
				}
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public void sendDataBack(byte[] data)
	{
		try {
			dos.write(data);
			dos.flush();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void sendData(byte[] data) {
		// TODO Auto-generated method stub
		try {
			dos.write(data);
			dos.flush();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

package net.tuolian.client;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

public class Client implements Runnable{

	Logger logger = LogManager.getLogger(Client.class);

	public Client()
	{
		
	}
	
	Socket socket = null;
	DataInputStream dis = null;
	DataOutputStream dos = null;
	
	public Client(String ip, int port)
	{
		try {
			socket = new Socket(ip, port);
			dis = new DataInputStream(socket.getInputStream());
			dos = new DataOutputStream(socket.getOutputStream());
			
			logger.info("connect to proxy server success");
			

		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void run()
	{
		while(true)
		{
			byte[] tmp =new byte[1024];
			try {
				if(dis.available()>0)
				{
					dis.read(tmp);
					logger.info(new String(tmp));
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			try {
				dos.write("hello from client ".getBytes());
				dos.flush();

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public void doTest()
	{
		new Thread(this).start();

	}
}

좋은 웹페이지 즐겨찾기