`
nbtlxx
  • 浏览: 253707 次
  • 性别: Icon_minigender_1
  • 来自: 宁波
社区版块
存档分类
最新评论

网络游戏服务器架构研究(-)代理服务器的简单实践

阅读更多
网络游戏的服务器框架中,通常需要代理服务器ProxyServer来解决高并发的请求。
目前实现了一个很简单代理服务器,没有考虑高并发的问题,只是实现了从客户端、代理服务器和游戏服务器的简单通信。
从客户端发送数据,经过代理服务器转发,到达游戏服务器
游戏服务器反射数据到代理服务器,后者在传递给客户端;

1. 负责接收来自客户端的消息
2. 负责转发来自服务器的消息
3. 管理客户端连接
   增加、删除客户端连接
   每个连接唯一标记
4. 管理服务器端连接
   根据serverid管理服务器端连接;

目前存在很多需要后续完善的地方
1. 客户端连接的管理,
       代理服务器接收到客户端连接后,产生随机的clientid, 构造出ClientConnectIon, 并且保存在map中待用
       目前的clientid是固定的
       所以目前还不支持多个客户端连接
       当然还涉及到客户端的断开的管理,从map中移除相关的连接;

2.   代理服务器的并发能力差
       后续考虑采用netty 或者mina来解决
       关键点是当客户端连接上来后,需要产生随机clientid, 保存到map中
       从游戏服务器下来的数据,能够找到正确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();

	}
}
分享到:
评论

相关推荐

    高性能并发服务器架构

    ### 高性能并发服务器架构 #### 一、引言 随着互联网技术的飞速发展,越来越多的在线服务面临着巨大的并发访问压力。为了满足用户需求,提高用户体验,高性能并发服务器架构成为了许多企业和开发者关注的重点。...

    高性能高并发服务器架构

    ### 高性能高并发服务器架构的关键知识点 ...以上内容总结了构建高性能高并发服务器架构的关键知识点和技术方案,涵盖了从理论到实践的各个方面。希望这些信息能够帮助读者更好地理解和实施高并发网站的架构设计。

    linux服务器架构

    ### Linux服务器架构详解 在IT领域中,Linux作为一款开源且功能强大的操作系统,在服务器领域有着广泛的应用。本文将从Linux服务器的基本概念出发,详细介绍几种常见的Linux服务器架构,并结合部分示例进行深入剖析...

    [详细完整版]服务器架构.doc

    服务器架构是构建高效稳定网络环境的关键,尤其对于校园服务器来说,长期运行后可能出现系统混乱,这时需要进行系统维护,甚至重装操作系统和应用软件。在进行服务器架构的维护时,有以下几个关键步骤: 1. **安装...

    誉天邹-Nginx网站架构1-5

    - **定义**: 反向代理是一种网络服务配置,其中客户端并不直接与目标服务器通信,而是通过一个代理服务器转发请求。 - **应用场景**: - **负载均衡**: 通过将请求分发到不同的后端服务器上,提高网站的整体性能和...

    高性能高并发服务器架构.pdf

    ### 高性能高并发服务器架构的关键知识点 #### 1. 高性能高并发服务器架构概述 - **定义**: 高性能高并发服务器架构是指能够同时处理大量用户请求,并且能够保持稳定性能的服务器架构。 - **重要性**: 在当前互联网...

    架构搭建-实践篇

    首先,Nginx是一款高性能的HTTP和反向代理服务器,常用于处理静态内容和作为反向代理进行负载均衡。在"nginx(业务Nginx配置).conf"文件中,你可以看到Nginx的各种配置项,如服务器监听端口、虚拟主机设置、路由规则...

    基于Linux的代理服务器的研究和实现.pdf

    总的来说,"基于Linux的代理服务器的研究和实现"这一主题涵盖了Linux操作系统、网络协议、系统开发等多个IT领域的知识,对于理解代理服务器工作原理,以及在Linux环境下构建安全、高效的网络服务具有重要价值。...

    网游服务器通信架构方案

    网游服务器通信架构是网络游戏开发中的核心部分,关系到游戏的稳定性和玩家体验。本文将深入探讨这一主题,为有志于网游服务器设计的开发者提供指导。 首先,网游服务器通信架构通常分为两大类:MMORPG(大型多人...

    Linux C_C++后端服务器架构开发1

    在Linux环境下进行C/C++后端服务器架构开发是一项复杂而关键的任务,涉及到多方面的技术知识。本课程主要涵盖了以下几个核心领域: 1. **精进基石**:这部分内容强调基础扎实的重要性,包括深入理解数据结构与算法...

    网络架构实践报告

    2. **请求分发**:代理服务器根据用户平台将请求转发到对应的负载均衡器,后者再将请求轮询至后端的Web服务器集群(如Nginx Web服务器A1和A2)。 3. **内容部署**:Web服务器上部署了相应的虚拟主机网站内容。 4. **...

    简单HTTP代理服务器-源码c++

    总的来说,"简单HTTP代理服务器-源码c++"是一个极好的学习资源,它涵盖了网络编程、HTTP协议、代理服务等多个重要概念,对于希望在这些领域深化技术的开发者来说,这是一个宝贵的实践项目。通过研究这个项目,你可以...

    企业服务器架构中MySQL读写分离部署运维实践手册

    ### 企业服务器架构中MySQL读写分离部署运维实践手册 #### 一、背景描述及其方案设计 ##### 1、业务背景描述 - **时间范围**:2014年6月至2015年9月 - **产品类型**:互联网动态站点商城 - **用户数量**:10,000至...

    网络游戏-使用虚拟交换代理控制网络接口.zip

    首先,虚拟交换代理(Virtual Switch Proxy)是一种网络虚拟化技术,常用于云计算和数据中心环境中,但同样适用于网络游戏的网络架构。它允许在一个物理主机上创建多个虚拟网络接口,每个接口都可以独立配置,模拟出...

    中小型研发团队架构实践:电商如何做企业总体架构示例分享

    ### 中小型研发团队架构实践:电商如何做企业总体架构示例分享 #### 一、系统概述及编写目的 本文档旨在全面阐述一个针对中小型企业研发团队的架构实践案例,特别是聚焦于电商领域的总体架构设计。编写的核心目的...

    基于c++ muduo网络库的集群聊天服务器,使用nginx实现负载均衡,使用reids消息队列实现跨服务器通信.zip

    《构建分布式聊天服务器:C++ muduo网络库、Nginx负载均衡与Redis消息队列》 在现代互联网服务开发中,构建可扩展、高可用的集群架构是至关重要的。本项目采用C++的muduo网络库作为基础,通过Nginx实现负载均衡,并...

    微服务架构设计与实践-内训方案.pdf

    ### 微服务架构设计与实践-内训方案 #### 第一课:知识原理篇 - **微服务定义及其本质**: - 微服务是一种架构风格,它将一个应用程序拆分成一组小型的服务,每个服务独立运行,通过轻量级通信机制(通常是HTTP...

Global site tag (gtag.js) - Google Analytics