各位师兄好:
兄弟做好了一个网关。原理如下:网关程序需要去连接一堆的远程机子,并且是保持长连接,对每一个SOCKET进行相应的处理。远程机子的HOST和PORT都保存在一个ArrayList类型的集合中,我从中依次读取出每一个HOST和PORT,读出一个后,我先判断目前SOCKET连接组中是否有该SOCKET,如果没有则新建该SOCKET,同时启动一个线程来处理相应的事务。在这个线程中,当通讯出错(可能是SOCKET断掉了)出现异常时,将连接组中的该SOCKET删除。程序如下:
public class AmClient {
private ThreadGroup threadGroup; ///线程组
private Map socketGroup = new HashMap(); //SOCKET连接组
ArrayList ipArray;////HOST与PORT的集合
String host;
int port;
public AmClient() {
threadGroup = new ThreadGroup(AmClient.class.getName());
}
public static ArrayList readXml() {
........
//////这里给ipArray这个集合附值,写入N个HOST和PORT
}
public static void main(String[] args) {
AmClient amClient = new AmClient();
ipList = readXml();
while (true) {
try {
amClient.socketRequest(ipList);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void socketRequest(ArrayList ipArray) {
BufferedReader in;
PrintWriter out;
Socket socket;
for (Iterator it = ipArray.iterator(); it.hasNext(); ) {
Map ipMap = (Map) it.next(); ///一行是一个Map
////取出参数
host = (String) ipMap.get("host");
port = Integer.parseInt((String) ipMap.get("port"));
String key = host + Integer.toString(port);
try {
if (socketGroup.get(key) == null) {
/////当连接没有建立时或连接断开了,新建SOCKET后再启动线程
System.out.println("controller start...");
socket = new Socket(host, port);
AmConnection k = new AmConnection(socket, ipMap);
socketGroup.put(key, socket); ///放入连接组中
} } catch (Exception e) {
////若出现断路情况,将socket从连接组中删除
if (socketGroup.get(key) != null) {
///若连接组中已有该连接
socketGroup.remove(key); ////从连接组中删除
}
System.out.println("socket断路了:" + e);
}
}
}
//处理每个SOCKET的线程
public class AmConnection extends Thread {
Socket client; //客户通信套接字
Map ipMap;
private String amHost,key;
private int amPort;
public AmConnection(Socket client, Map ipMap) {
super(threadGroup,
client.getLocalAddress() + Integer.toString(client.getPort()));
this.client = client;
this.ipMap = ipMap;
amHost = (String) ipMap.get("host");
amPort = Integer.parseInt((String) ipMap.get("port"));
key = amHost + Integer.toString(amPort);
start();
}
public void run() {
try {
........
////作相应的处理
} catch (Exception e) {
////若出现断路情况,将socket从连接组中删除
if (socketGroup.get(key) != null) {
///若连接组中已有该连接
socketGroup.remove(key); ////从连接组中删除
}
System.out.println("socket断路了:" + e);
interrupt(); //中断该线程
}
} }
}
现在的问题是:我程序运行后,功能倒是可以实现,可是CPU的占用率达到了100%。后来我在main方法中加了一句
try {
amClient.socketRequest(ipList);
Thread.sleep(5000); //就加了这句
}
CPU就正常了。这是为什么呢?望知情者详细解释,谢谢。
兄弟做好了一个网关。原理如下:网关程序需要去连接一堆的远程机子,并且是保持长连接,对每一个SOCKET进行相应的处理。远程机子的HOST和PORT都保存在一个ArrayList类型的集合中,我从中依次读取出每一个HOST和PORT,读出一个后,我先判断目前SOCKET连接组中是否有该SOCKET,如果没有则新建该SOCKET,同时启动一个线程来处理相应的事务。在这个线程中,当通讯出错(可能是SOCKET断掉了)出现异常时,将连接组中的该SOCKET删除。程序如下:
public class AmClient {
private ThreadGroup threadGroup; ///线程组
private Map socketGroup = new HashMap(); //SOCKET连接组
ArrayList ipArray;////HOST与PORT的集合
String host;
int port;
public AmClient() {
threadGroup = new ThreadGroup(AmClient.class.getName());
}
public static ArrayList readXml() {
........
//////这里给ipArray这个集合附值,写入N个HOST和PORT
}
public static void main(String[] args) {
AmClient amClient = new AmClient();
ipList = readXml();
while (true) {
try {
amClient.socketRequest(ipList);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void socketRequest(ArrayList ipArray) {
BufferedReader in;
PrintWriter out;
Socket socket;
for (Iterator it = ipArray.iterator(); it.hasNext(); ) {
Map ipMap = (Map) it.next(); ///一行是一个Map
////取出参数
host = (String) ipMap.get("host");
port = Integer.parseInt((String) ipMap.get("port"));
String key = host + Integer.toString(port);
try {
if (socketGroup.get(key) == null) {
/////当连接没有建立时或连接断开了,新建SOCKET后再启动线程
System.out.println("controller start...");
socket = new Socket(host, port);
AmConnection k = new AmConnection(socket, ipMap);
socketGroup.put(key, socket); ///放入连接组中
} } catch (Exception e) {
////若出现断路情况,将socket从连接组中删除
if (socketGroup.get(key) != null) {
///若连接组中已有该连接
socketGroup.remove(key); ////从连接组中删除
}
System.out.println("socket断路了:" + e);
}
}
}
//处理每个SOCKET的线程
public class AmConnection extends Thread {
Socket client; //客户通信套接字
Map ipMap;
private String amHost,key;
private int amPort;
public AmConnection(Socket client, Map ipMap) {
super(threadGroup,
client.getLocalAddress() + Integer.toString(client.getPort()));
this.client = client;
this.ipMap = ipMap;
amHost = (String) ipMap.get("host");
amPort = Integer.parseInt((String) ipMap.get("port"));
key = amHost + Integer.toString(amPort);
start();
}
public void run() {
try {
........
////作相应的处理
} catch (Exception e) {
////若出现断路情况,将socket从连接组中删除
if (socketGroup.get(key) != null) {
///若连接组中已有该连接
socketGroup.remove(key); ////从连接组中删除
}
System.out.println("socket断路了:" + e);
interrupt(); //中断该线程
}
} }
}
现在的问题是:我程序运行后,功能倒是可以实现,可是CPU的占用率达到了100%。后来我在main方法中加了一句
try {
amClient.socketRequest(ipList);
Thread.sleep(5000); //就加了这句
}
CPU就正常了。这是为什么呢?望知情者详细解释,谢谢。
谢谢回复
TO 回复人: cuij7718(沸腾的音乐 http://sunfruit.blogchina.com) ( )
那应该如何理解多线程呢?象这样的情况,同时要连接多个远程端,而且又必须保证每个SOCKET的实时通讯。不用线程来处理,怎么做才能保持每个SOCKET的长连接???
TO 回复人: gemouzhi(gemouzhi)
那正确的方向是什么,请详细说明,谢谢。
谢谢你的回复,我把我网关的功能需求说明一下:
1、首先有多个远程机子。
2、网关这边要先发送一条请求信息去连接远程机子。远程机子收到请求信息后,将一条远程机子上的消息回送给网关。网关收到后,进行相应的处理后再发送请求信息给远程机子。如此循环,即网关发一条请求,远程才会回送一条消息。
3、若有发现连接断开的情况,将进行重连。
基本需求就是这样,我也不想保持长连接,可是如果不保持的话,那么如何保证与每个远程机子的实时通讯?难道每次都要new Socket一下,处理一条消息后就close掉。连接建立起来后,双方的通讯频率是很高的,这也是客户要求保持长连接的原因。
所以我的程序就是考虑把存放远程HOST和PORT的ipArray遍历一下,每取出一条HOST和PORT,就查一下是否有在连接组socketGroup中有该SOCKET了,如果没有,就 new Socket(host, port),同时启用一个线程来处理这个SOCKET的实时通讯的事务。如果连接组中已存在这个SOCKET,那就不管了,因为这个SOCKET的线程已经在启动运行了。
程序在第一次运行的时候,肯定所有的SOCKET都要新建的。然后,只有在这个SOCKET的通讯出现错误了(基本上就是SOCKET异常断开了),才会新建连接的。
至于主方法中
while (true) {
try {
amClient.socketRequest(ipList);
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}}
amClient.socketRequest(ipList);这句我也觉得放在while (true)怪怪的,正如你说的不应该去阁5秒钟,就去问每一个小朋友。可是我不放在while (true)里,那么程序一运行起来后,CPU就占用到100%,而且放在while里面的还有一个好处就是,当发现SOCKET断开后,每隔5秒会一次重连的尝试,否则就会一直进行重连操作至到连接成功为止,这样比较占资源吧。
望师兄指教,谢谢。
远程计算机的当机 或 网络异常 或 硬件上的异常 或 人为结束掉进程
至于第二个问题:我的网关所放的位置很有可能是不固定的。如果是固定的,我曾经考虑过将网关即当客户端又当服务端,即一方面它向远程机子不停地发请求,一方面它开放一个端口来监听远程机子发过来的信息(并做相应处理)。这里需要远程的机子在收到请求后,不是直接将信息应答,而是用一个SOCKET去连接我的网关(我的IP和开放的端口),将信息传给网关。
这种方式已经被客户拒绝了,他们不允许这么做。所以我想我的网关位置固定与否就没多大关系了啦。
谢谢指教。另:师兄是否有QQ或MSN可以交流?
怎么用?能不能说的详细些???
http://www-128.ibm.com/developerworks/cn/java/j-javaio/
还有相关的信息,在网上搜搜吧
不要用线程
连接是资源,应按资源池的机制实现
管理几个连接池,每个连接池对应不同的远程机子
每个连接池有ip、port、初始连接数,最大连接数等参数
ResourcePoolManager负责参数读取、所有资源池初始化、销毁、关闭、重启、取空闲连接、返还连接等等
ResourcePool负责单个池的维护,ResourcePool中包含多个Resourceable实例
这样你可以管理监控每个池甚至每个连接的状态
NIO的socket有没有线程处理的例子。