当前位置:编程学习 > JAVA >>

java长连接异步单工模式

/**
 * @author 唐望
 * 
 */
public class SocketServerBank extends Thread {

/**
 * logger对象
 */
private static final Logger logger = Logger.getLogger(SocketServerBank.class);

private ServerSocket instanceBank;// 唯一实例

private ExecutorService executorService;// 线程池


/**
 * 服务设置
 */
private int port = 4321;// 缺省绑定端口
private int threadCount = 10;// 缺省池中的线程数

/**
 * 服务状态
 */
private static boolean isRunning = false;// 服务是否正在运行

private TransFacade transFacade; // 调用提供传输处理类

/**
 * @param transFacade
 *            the transFacade to set
 */
public void setTransFacade(TransFacade transFacade) {
this.transFacade = transFacade;
}

/**
 * @param port
 *            the port to set
 */
public void setPort(int port) {
this.port = port;
}

/**
 * @param threadCount
 *            the threadCount to set
 */
public void setThreadCount(int threadCount) {
this.threadCount = threadCount;
}



Socket socket = null;


/**
 * 启动Socket服务
 * 
 * @throws OTSTransException
 */
public void run() {
if (isRunning == true) {
logger.warn("启动失败,只能同时运行一个Socket服务!");
return;
}

try {

InetSocketAddress endpoint = new InetSocketAddress(port);

instanceBank = new ServerSocket();
instanceBank.bind(endpoint);

isRunning = true;

} catch (IOException e) {
logger.error("服务器启动失败!" + e.getMessage(), e);
return;
}

// 设置线程池的线程数
executorService = Executors.newFixedThreadPool(threadCount);

// Runtime的availableProcessor()方法返回当前系统的CPU数目.
logger.info("当前系统的CPU数目=" + Runtime.getRuntime().availableProcessors());

logger.info("启动Socket服务成功,线程数=" + threadCount);

try {
socketTool = new SocketTool(yl_ip, yl_port, fs_timer);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


while (true) {

try {

// 接收客户连接,只要客户进行了连接,就会触发accept();从而建立连接
if (instanceBank.isBound() && !instanceBank.isClosed()) {

socket = instanceBank.accept();

socket.setKeepAlive(true);

executorService.execute(new Handler1(socket, transFacade));

}
} catch (RejectedExecutionException e) {
logger.warn("未能处理的请求,ip地址=" + socket.getInetAddress());
} catch (IOException e) {
e.printStackTrace();
}

}

}
}

class Handler1 implements Runnable {

private Socket socket;

private TransFacade transFacade;

private BufferedInputStream in;

private final int BUFFER_SIZE = 1024;

/**
 * logger对象
 */
private static final Logger logger = Logger.getLogger(Handler1.class);

public Handler1(Socket socket,  TransFacade transFacade) {
this.socket = socket;
this.transFacade = transFacade;
}


public void run() {

logger.info("接收socket链接, " + socket.getInetAddress() + ":"
+ socket.getPort());

SocketServerBank.jstimer = new Long(0);

try {

in = new BufferedInputStream(socket.getInputStream());

byte[] buffer = new byte[BUFFER_SIZE];

StringBuffer request = new StringBuffer();

int tail = TransConsts.TAIL_SPLIT_WORD.charAt(0);

int result = 0;
while (result != -1) {
result = in.read(buffer);
String cur = null;

if (result != -1) {
cur = new String(buffer, 0, result);
request.append(cur);
}

if (result < BUFFER_SIZE || cur == null
|| cur.charAt(cur.length() - 1) == tail) {
break;
}
}

String req = request.toString();

byte[] bf = new byte[4];
System.arraycopy(buffer, 0, bf, 0, 4);

logger.info("请求报文前四位:"+new String(bf));
//请求报文内容为空时不做处理    请求报文为空闲报文0000时  不作处理
if (!"".equals(req) && !("0000").equals(new String(bf))) {
        
Parser_bank pb=new Parser_bank();
TransResponse res = transFacade.getMacKey();
    //String getIsoInfo
Map map= pb.getBankInfo(buffer, res.getMacKey());
res = transFacade.doYWCL((String)map.get("message"));

String responseMsg =res.getISOResponse();//"0"+TransConsts.COLUMN_SPLIT_WORD+"00"+TransConsts.DATATYPE_SPLIT_WORD+"000000"; //

byte[] responses= pb.returnISOInfo(map,buffer,responseMsg);


}

} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {

// QueueManager.getInstance().releaseThreads();

try {
in.close();
/*
if (socket != null) {
logger.info("关闭 socket链接");
socket.close();
}*/
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
}

服务器能正常接收到客户两次心跳包,后客户就得重连一次,客户端是用C写的一个工具!服务器没有结束socket的命令,不知道整个链路是怎么断的,且测试后电脑上存在大量的COLSE_WAIT和TIME_WAIT端口没释放 socket java tcp通信长连接 --------------------编程问答-------------------- java的socket机制是不都是一请求,一响应呢?为什么在实现异步单工长连接没接收到两次就没反应了,得重连。服务器没有发关闭socket 的命令。整个链路就断了。 --------------------编程问答-------------------- 楼主的代码太长太乱了,而且贴得不全,这给回复的人带来很大的麻烦,希望能改正!

大概看了一下,再接收后的线程处理函数为什么楼主只关闭in.close();呢?TCP连接的资源肯定不止in需要关闭,有没有试过直接socket.close()?

另外,COLSE_WAIT基本上就是由于代码没有正确关闭TCP连接造成的,time_wait的状态是正常的TCP释放状态,这个状态默认消失的时间比较长,可以尝试修改系统配置改正。 --------------------编程问答-------------------- socket.close();执行了跟没执行都一样,不过按照长连接的的说法,是不需要关闭的。COLSE_WAIT是因为服务关了,客户端还没检测出来,估计是缓存导致判断失效的吧。单工异步的场连接是两条链路,而作为服务器的我们边,没主动关闭连接过,而客户那边则检测出我这边网络中断。这是我不能理解的地方。如 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- LS的图,客户端部分,process之后,有Loop back and wait another communication. 
按楼主的说法,是要实现一个‘异步单工长连接’,这里有2个问题:
1. 连接断了,就必然是有一方主动断开(发送FIN报文)。个人认为TCP本身是没有长短连接的概念的(尽管网  上有不少分析TCP长短连接的),两方都不主动断开,它就是一个长连接(直到连接超时)。所以楼主在处理完客户端的请求(上图的process之后),应该再进入一个循环从inputstream读的过程(楼主的代码里,在一个线程里处理完之后,把inputstream close了,这显示不是要继续处理)
2. 楼主说服务器端不需要关闭。如果客户端始终是有数据发过来,那连接会一直保持,但是如果客户端停止发送数据了,这个连接始终还是会关闭的(超时)。所以如果一个socket server不主动关闭,这是不合理的(因为你不能保证客户端一定会主动关闭连接),你至少应该保证:在一段时间内如果没有收到客户端的任何东西,那这个连接理应被关闭了 --------------------编程问答-------------------- 里面加了定时时器,如果长时间(多长时间根据需要自己配置)没收到客户端的请求就会主动关闭连接。按图描述accept()在while体外。这样的客户端的请求信息读不到,现在加在while体里面能读到客户的请求,每接到两次又的从链  才能有新的信息进服务器。
补充:Java ,  Eclipse
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,