네트워크 게임 서버 구조 연구(-) 프록시 서버의 간단한 실천
현재 매우 간단한 프록시 서버를 실현했고 높은 병행 문제를 고려하지 않고 클라이언트, 프록시 서버와 게임 서버로부터의 간단한 통신만 실현했다.
클라이언트로부터 데이터를 전송하고 프록시 서버를 통해 게임 서버에 전송
게임 서버는 데이터를 프록시 서버에 반사하고 후자는 클라이언트에게 전달한다.
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();
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
조밀한 게임을 Scratch로 만들어 보았다. 그 1.2021년 1월 7일에 스가 총리가 긴급 사태 선언을 발령했습니다. 역시 「밀」이 좋지 않은 일이라고, 재차 생각했으므로 넷에서 보인 명작 을 마음대로 흉내내 Scratch로 만들어 보았습니다. <완성 이미지> 링크...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.