公司项目,要求定时去采集器采集数据,采集器内置socket服务器,现在我用mina短连接,每次都可以收到数据
但是用tcp查看器查看有好多的 [System Process] TIME_WAIT,而且是越来越多
代码如下:
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.ReadFuture;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.xmgsd.utils.DESPlus;
/**
public class RoomMonitorClent {
private static final Logger log = LoggerFactory.getLogger(RoomMonitorClent.class);
private String host;
private int port;
NioSocketConnector connector;
public RoomMonitorClent(String host, int port) {
this.host = host;
this.port = port;
init();
}
public void init() {
connector = new NioSocketConnector();
connector.setConnectTimeoutMillis(30000L);
// connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new YourCodecFactory()));
SocketSessionConfig cfg = connector.getSessionConfig();
cfg.setUseReadOperation(true);
}
/**
*
* @param msg
* @return
*/
public String sendMessage(String msg) {
InetSocketAddress addr = new InetSocketAddress(host,port);
IoSession session = null;
try {
session = connector.connect(addr).awaitUninterruptibly().getSession();
connector.getSessionConfig().setSoLinger(0);
IoBuffer buffer = IoBuffer.allocate(100, true);// 分清楚direct和heap方式的缓冲区别
buffer.setAutoExpand(true);// 自动扩张
buffer.setAutoShrink(true);// 自动收缩
buffer.put(DESPlus.hexStr2ByteArr(msg));
buffer.flip();
buffer.free();
// 发送
session.write(buffer).awaitUninterruptibly();
// 接收
ReadFuture readFuture = session.read();
if (readFuture.awaitUninterruptibly(500, TimeUnit.MILLISECONDS)) {
IoBuffer result = (IoBuffer)readFuture.getMessage();
System.out.println("收到服务器发来的信息: " + result);
//返回的信息字符串
return result.getHexDump().replace(" ", "");
// TODO 处理消息
} else {
// 读超时
System.out.println("向服务器:"+host+":"+port+"发送命令:"+msg+"未响应,读取超时,请确定该设备正常运行!");
log.error("向服务器:"+host+":"+port+"发送命令:"+msg+"未响应,读取超时,请确定该设备正常运行!");
return null;
}
}
catch (RuntimeIoException e) {
System.out.println("服务器:" + host + ":" + port + "未能连接!");
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
finally {
// 断开
if(session != null){
session.close(true);
//session.getService().dispose();
connector.dispose();
}
}
return null;
}
/**
* 根据返回结果获取温度
* @param strinput
* @return
*/
public static String getTemperature(String strinput)
{
String temperature = null;
if (strinput.length()==18&&strinput.substring(0, 2).equals("01"))
{
//以下是温度计算
String tmp1=strinput.substring(6, 8);
String tmp2=strinput.substring(8, 10);
int tmp3=Integer.valueOf(tmp1,16);
int tmp4 = Integer.valueOf(tmp2,16);
temperature=""+(float)(tmp3*256+tmp4)/10;
//System.out.println("温度是:"+(float)(tmp3*256+tmp4)/10+"℃");
}
return temperature;
}
/**
* 根据返回结果获取湿度
* @param strinput
* @return
*/
public static String getHumidity(String strinput)
{
String humidity=null;
if (strinput.length()==18&&strinput.substring(0, 2).equals("01"))
{
//以下是湿度计算
String _tmp1=strinput.substring(10, 12);
String _tmp2=strinput.substring(12, 14);
int _tmp3=Integer.valueOf(_tmp1,16);
int _tmp4 = Integer.valueOf(_tmp2,16);
humidity = (float)(_tmp3*256+_tmp4)/10+"";
//System.out.println("湿度是:"+(float)(_tmp3*256+_tmp4)/10+"%");
}
return humidity;
}
public static void main(String[] args) throws Exception {
for (int i = 0; i < 10; i++) {
RoomMonitorClent clent = new RoomMonitorClent("192.168.0.250",27011);
// clent.sendMessage("0203000300023438");
String s = clent.sendMessage("010300030002340B");
System.out.println(s);
}
}
}
如果用长连接的话 如何去做?
长连接就是只要客户端程序不退出,连接不出异常,你就一直用同一个连接发送数据,不要每次发送都去创建新的连接。
如果用短连接的话,通常客户端都会有一个连接池用于复用这些连接。例如JDK的HTTP支持。频繁地创建和关闭连接操作系统受不了,原因上面解释得很到位了。
我再这说句可能许多人都不愿意听的话,包括有几年工作经验的很多人都太迷信JavaNIO了。没有几百个连接以上完全没必要用NIO。其实你这种需求用BIO做几行代码就搞定了,又清晰又简单,看看Java入门书籍就能做到,完全没必要去搞什么MINA。
如果学过MINA的话,学BIO更容易,和MINA的IOFilter机制很像,BIO可以在Input/Output上附加各种机制,而且更简单,甚至一行代码就能搞定。例如:
[code="java"]
BufferedReader in = new BufferedReader(new InputStreamReader(new BufferedInputStream(sock.getInputStream())));
for(;;)
{
String msg = in.readLine();
if(msg == null)//end of stream
break;
processMessage(msg);
}
in.close();//省略了异常处理机制
sock.close();//实际代码中要处理异常
boolean autoFlush = true;
PrintWriter out = new PrintWriter(new BufferedOutputStream(sock.getOutputStream()),autoFlush);
public void sendMessage(String msg) throws IOException
{
synchronized(out)
{
out.println(msg);
}
}
[/code]
这段代码是直接打出来的,如果有语法错误请自行修改。
很多TIME_WAIT 是正常的。。
[quote]TIME_WAIT状态
TCP中有关网络编程中TIME_WAIT状态不容易理解。该端点停留在这个状态的持续时间是最常分节生命期(maximum segment lifetime,MSL)的两倍。TIME_WAIT状态有两个存在的理由:(1)可靠地势险TCP全双工连接的终止。该理由容易理解,主要是为了发送最终的ACK(2)允许老的重复分节在网络中消逝。该理由是说TCP必须防止来自某个连接的老的重复分组在该连接已终止后再先,从而被误解成属于同一连接的某个新的化身。
[/quote]
关于这个TCP可以看http://zhxing.iteye.com/blog/934851 我这个TCP笔记,或者会清楚点
做不做长连接,我觉得要看你的采集数据的频率值得不值得去做长连接。。
所谓的长连接也就是维护一条连接而已。不需要关闭就行了。。
用短连接还不如用HTTP协议呐