多个进程如何共享同一个socket
需求:为了使游戏平台和具体的游戏,比如QQ游戏大厅和地主,杀人,放火游戏进程分离,但是却有要共享同一个socket连接
C\C++实现:在windows c下编程实现可以用复制SOCKET句柄WSADuplicateSocket或共享内存的方式,但在java中不知用何种方式,或者类似的方式,我search了一下,似乎JOMP说的是共享内存,但却不知如何使用。还有真的有必要用这种方式实现游戏平台和具体的游戏分离吗,有什么更好的实现方式呢?
[解决办法]
JVM据我所知,没有什么高效的进程间的通信、共享机制。
因为,不同的操作系统,其进行间的通信、共享机制都有所不同,那么,
对于跨平台,可移植性,确实是一种挑战。
一般来讲,常见的Windows和Unix系统,都是基于线程的操作系统。
也就是说,CPU的时间片会按照系统的策略分配给每一个线程,而非进程。
那么,在没有什么特殊需求的情况下,我们都会选择多线程技术来编程,而非多进程技术。
还是说点有用的吧:
我想,楼主说的问题,应该是针对服务端的程序开发。
不知道,楼主对FTP协议是否有所了解。
我指的是,控制指令与实际文件传输使用不同Socket来传输。
(这样会使程序设计简单,逻辑会比较清晰)
所以,我当然也会推荐楼主采用这种思想,来设计游戏大厅与具体游戏的关系。
实际情况下,如果游戏大厅和具体的游戏采用同一个Socket传输,那么,具体游戏的增删,会影响到通信协议的修改。
而且,客户端的编程,也会比较复杂。
Java的进程间通信,一般都是用TCP、UDP或者RMI之类的东西来实现的。所以,Socket共享,好象不太现实。
这种情况下,大厅服务器会起到类似Socket代理服务器的作用。(也就是说,如果是游戏的数据,它会转发到对应的游戏服务器上)
我推荐的程序架构是这样的:
大厅服务器与客户端采用一个Socket进行通信,各游戏采用各自的Socket进行通信(因为不同的游戏,通信数据不同,协议也不尽相同)。
大厅服务器上存放一些跟游戏服务器的相关信息(比如服务器状态,服务器IP,游戏端口之类的)
客户端的开发就比较结构清晰了。
首先,开发和大厅服务器的程序。
其次,当有新游戏要添加至大厅的时候。只要在大厅服务器上添加相关的信息就可以了。
因为,游戏的客户端程序与游戏服务器程序,本身可以相对独立的成为一个系统。
不知道我这样解释,楼主是否明白。
没有解决楼主的问题,实在不好意思。
[解决办法]
先提一点:java有进程这种机制吗?就像linux一样,伪进程
------------------------
你还是没有建立在OO的基础上思考你的设计
只要你是OO的,你就能区分游戏大厅和各类游戏,因为你有大厅类,各种游戏类
然后做好分工,你的每个类负责干一些什么事情
具体到你的需求
类的生成和分配
程序运行后肯定首先有大厅类的实例,然后根据用户选择,大厅类生成对应的游戏类实例,让其运行
你完全可以大家同用一个socket
先生成socket,再生成大厅,把socket传给大厅
大厅生成socket的时候,大厅再把socket传给游戏类
你也可以各自使用自己的socket
这样socket就由类自己去创建
你还可以创建一个socketHelper
专门处理数据的收发
然后是分工
划分好那些数据应该由那些类负责处理
你所说的玩家进入、退出、逃跑等消息,这时应该是大厅类所负责处理的
如果每个游戏都需要"知晓" "这类"消息,那就由大厅根据需要去通知每个游戏类
[解决办法]
另外,我不是太明白你为什么强调用进程而不能用线程?
是因为你要求分离,并把程序分成不同的文件包吧,然后大厅运行游戏的时候大厅excus()一个jar?
[解决办法]
public interface iGame { public void gameLogic();}
[解决办法]
import java.io.File;import java.net.MalformedURLException;import java.net.URL;import java.net.URLClassLoader;public class Room { private String[] myGames; private String[] myGamesClassNames; private String[] myGamesJarAbsolutePath; public Room() { } private void flushGames() { //这里的配置关系可以从配置文件中读取 File gameClassDir=new File("d:/games"); File[] gameClassFiles=gameClassDir.listFiles(); this.myGames=new String[gameClassFiles.length]; this.myGamesClassNames=new String[gameClassFiles.length]; this.myGamesJarAbsolutePath=new String[gameClassFiles.length]; for(int i=0 ;i<gameClassFiles.length;i++) { myGames[i]=gameClassFiles[i].getName().replaceAll(".jar", ""); myGamesClassNames[i] = gameClassFiles[i].getName().replaceAll(".jar", ""); myGamesJarAbsolutePath[i] = gameClassFiles[i].getAbsolutePath(); } } private void startGame(int index) throws InstantiationException, IllegalAccessException, ClassNotFoundException, MalformedURLException { String name=myGames[index]; String classNames=myGames[index]; String jarAbsolutePath=myGamesJarAbsolutePath[index]; URL jarUrl=new URL("file:/"+jarAbsolutePath); URLClassLoader loader = new URLClassLoader(new URL[]{jarUrl});//加载对应的jar Class c = loader.loadClass(classNames); //用加载了jar的loader来加载对应的游戏类文件 iGame game=(iGame)c.newInstance(); game.gameLogic(); } public void test() { System.out.println("游戏有:"); for(int i=0;i<myGames.length;i++) { System.out.println(i+" - "+myGames[i]); } int selected = Integer.parseInt(System.console().readLine()); try { startGame(selected); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { Room r=new Room(); r.flushGames(); r.test(); r.flushGames(); r.test(); r.flushGames(); r.test(); r.flushGames(); r.test(); }}
[解决办法]
这样也不需要配classpath了
只需要"java Room"即可
-------------------测试步骤
第一次d:/games里只放双扣
D:\workspace\sometest\room\bin>java Room
游戏有:
0 - ShuangKou
(先不要选,把其他两个游戏放进games目录)
0
this is ShuangKou Game running.......
(更新的游戏显示出来了,显示是当然的)
游戏有:
0 - ChuDaDi
1 - GongZhu
2 - ShuangKou
1
this is GongZhu Game running.......
(成功运行!!)
游戏有:
0 - ChuDaDi
1 - GongZhu
2 - ShuangKou
2
this is ShuangKou Game running.......
游戏有:
0 - ChuDaDi
1 - GongZhu
2 - ShuangKou
[解决办法]
另外
经过测试,已经加载过的游戏,再删除就不行了,因为文件被使用
不过我想如果是使用配置文件的
可以通过配置文件来设置成下次大厅运行时删除
---------------------------
另:
用URLClassLoader+配置文件的话,游戏的文件管理起来就更加方便了
游戏名 - 游戏类名 - 游戏jar文件绝对路径
[解决办法]
game工程能否应用到room下的组件lib?
能用到,game用room的lib里的jar就像用java常用jar包一样,import进来就可以了