java socket 长连接奇怪的问题
我有一个类,负责通过SOCKET长连接与服务器端通讯。这个循环读取一个队列来发送。
问题来了,在本类的MAIN方法中向队列中添加数据,就可以发送出去,在SERVLET中,通过HTTP请求添加,就是发送不出去!请大家帮忙看看,谢谢。下面是这个主要类的代码。
/**java socket 长连接 --------------------编程问答-------------------- , socket 没用过 ,只用过mina 。mina已经在封装好了 socket ,所以还是挺好的 。个人感觉这个框架够用 。 --------------------编程问答-------------------- 有没有报错啊 发出来看看 --------------------编程问答-------------------- 是不是会抛异常;IOException?
*
*/
package com.dianshangwang.lianhepayfront.service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import com.dianshangwang.lianhepayfront.global.Config;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
* @author lay
* @date 2013年11月4日
*/
public class IcardpayClient {
private static Logger log = Logger.getLogger(IcardpayClient.class);
private static Socket socket;
private static BufferedReader reader;
private static PrintWriter writer;
private static Thread sendThread;
private static Thread receiveThread;
private static Thread monitorThread;
private static boolean isRunning = false;
/**
* 心跳计数器 若此值与当前时间戳值小于60000则认定断线,进行重联操作
*/
private static Long heartbeatTimestamp = System.currentTimeMillis();
private static IcardpayClient instance = new IcardpayClient();
private IcardpayClient() {
}
public static IcardpayClient getInstance() {
return instance;
}
public static void main(String[] args) {
BasicConfigurator.configure();
IcardpayClient client = new IcardpayClient();
client.start();
MsgQueue.sendQueue.add("{\"agentNo\":\"A10342hp\",\"tradeType\":\"256\",\"sessionId\":\"1\"}");
}
public void start() {
init();
sendThread = new Thread(new SendThread());// 启动读线程
receiveThread = new Thread(new ReceiveThread());// 启动收线程
monitorThread = new Thread(new MonitorThread()); // 启动监视线程
sendThread.setName("icardpay-send-thread");
receiveThread.setName("icardpay-receive-thread");
monitorThread.setName("icardpay-monitor-thread");
// sendThread.setDaemon(true);
// receiveThread.setDaemon(true);
// monitorThread.setDaemon(true);
sendThread.start();
log.info("SOCKET发送线程开启!");
receiveThread.start();
log.info("SOCKET接收线程开启!");
// monitorThread.start();
// log.info("SOCKET监视线程开启!");
}
public void restart() {
stop();
init();
}
public void stop() {
isRunning = false;
}
private void init() {
socket = new Socket();
try {
socket.setKeepAlive(true);
socket.connect(new InetSocketAddress(Config.icardpayHost, Config.icardpayPort));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
writer = new PrintWriter(socket.getOutputStream());
heartbeatTimestamp = System.currentTimeMillis();
log.info("已创建与支付通的SOCKET连接!");
isRunning = true;
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void write(String msg) {
writer.println(msg);
writer.flush();
log.info(Thread.currentThread().getName() + "发送:" + msg);
}
private String read() throws IOException {
String msg = reader.readLine();
if (msg != null) {
log.info("接收:" + msg);
}
return msg;
}
class SendThread implements Runnable {
@Override
public void run() {
while (isRunning) {
if (!MsgQueue.sendQueue.isEmpty()) {
String v = MsgQueue.sendQueue.poll();
write(v);
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class ReceiveThread implements Runnable {
@Override
public void run() {
while (isRunning) {
String content = null;
try {
content = read();
} catch (IOException e1) {
log.error("SOCKET读取异常,将重新启动。。。", e1);
restart();
continue;
}
if (null == content || content == "") {
continue;
}
JsonObject obj = new JsonParser().parse(content).getAsJsonObject();
if (obj.has("tradeType") && "0".equals(obj.get("tradeType").getAsString())) {
// 收到心跳包, 刷新计数器
heartbeatTimestamp = System.currentTimeMillis();
continue;
}
if (!obj.has("sessionId")) {
log.info("收到未标识的包:" + obj.toString());
continue;
}
String id = obj.get("sessionId").getAsString();
if (MsgQueue.listeners.containsKey(id)) {
MsgQueue.listeners.get(id).received(content);
MsgQueue.listeners.remove(id);
} else {
log.info("接收到过期包:" + content);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// 忽略
}
}
}
}
class MonitorThread implements Runnable {
String heartbeat = "{\"agentNo\":\"A10342hp\",\"tradeType\":\"0\"}";
@Override
public void run() {
while (isRunning) {
if (System.currentTimeMillis() - heartbeatTimestamp >= 60000) {
// SOCKET已失效
restart();
}
// 发送心跳包
write(heartbeat);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// 忽略
}
}
}
}
}
补充:Java , Java EE