break; case 0x20: //查询数据回应 ,处理并存入数据库 if (login_succed==true) { switch (packet_cmd_reserved) { case 0x00://正常响应 System.out.println("recive_valid_length is "+ recive_valid_length); byte send_meter [] = new byte [recive_valid_length]; for (int i = 0; i < send_meter.length; i++) { send_meter[i] = reciver_buffer[i+8]; } boolean crc_check = ModbusCrc16.checkBuf(send_meter); System.out.println("crc check is "+crc_check); if (crc_check) { MeterDatas meter = new MeterDatas(send_meter, ccid); if (meter.MeterUpdate()) { //存到数据库或者直接传给需要客户端 System.out.println("DIO is :"+(0xff & meter.DIO)); System.out.println("Ua is :"+meter.Ua); System.out.println("Ub is :"+meter.Ub); System.out.println("Uc is :"+meter.Uc); System.out.println("HZ is :"+meter.Hz); } else { System.out.println("meter datas parse error!"); } } break; case 0x01://异常响应 System.out.println("read meter error!"); break; default: break; } }
break; case 0xd0: String eccidString = Integer.toString(((0xff & reciver_buffer[8])<<8)+(0xff & reciver_buffer[9])); System.out.println("eccid is "+ eccidString); sendSocket=socketHashMap.get(eccidString); if (sendSocket!=null) { OutputStream sop = sendSocket.getOutputStream(); System.out.println("sendSocket is exsitl!"); valid_data_length = 0x0b; byte sum1=0; byte meterAddr =(byte) (0xff & reciver_buffer[10]); byte meterCmd = (byte)0x10; int regStartAddr =0x21; int regCount = 0x01; int crcValue=0x00; int eccid =Integer.parseInt(eccidString, 16); byte toggleButton=0; if ((0xff & reciver_buffer[11])==0x01) { toggleButton =(byte)0xf0; } byte send_meter [] = new byte []{meterAddr,meterCmd,(byte)(regStartAddr>>8),(byte)regStartAddr,(byte)(regCount>>8),(byte)regCount,0x02,toggleButton,0x00}; ModbusCrc16 modbusCrc16 = new ModbusCrc16(); modbusCrc16.update(send_meter, send_meter.length); crcValue=modbusCrc16.value; byte send_control [] = new byte[]{(byte) 0x4c,0x53,(byte)0xdf,0x00,(byte)(eccid>>8),(byte)eccid,(byte)valid_data_length,(byte)(valid_data_length>>8), meterAddr,meterCmd,(byte)(regStartAddr>>8),(byte)regStartAddr,(byte)(regCount>>8),(byte)regCount,0x02,toggleButton,0x00,(byte)crcValue,(byte)(crcValue>>8),sum1,0x0d,0x0a}; for(int i=0;i<send_control.length-3;i++) sum1+=0xff & send_control[i]; send_control[send_control.length-3]=(byte)sum1; sop.write(send_control, 0, send_control.length); System.out.println("send control meter cmd finished!"); sendSocket = null; } else { System.out.println("sendSocket is null!"); }
服务器端 ServerSocket ss= new ServerSocket(端口号 如1555); //创建ServerSocket对象
有啦ss 在调用ss的accept方法返回一个Socket对象 Socket s=ss.accept(); 写到这一步 服务器就阻塞到这里啦 一直等待客服端连接他
OutputStream os=s.getOutputStream();//向客户端发送信息
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(os));
bw.write("服务器连接上.....");客服端 Socket s=new Socket("localhost",端口号);//这个端口号一定要与服务器的端口号相同
通过s 得到一个inputstream对象 InputStream is=s.getInputStream(); 有啦InputStream 我们就可以通过bufferedReader读取服务器给客户端发来的信息 BufferedReader br=new BufferedReader
(new nputStreamReader(is)); String s=br.readLine();//s就是服务器发来的信息
其实说透啦 主要就是通过Socket类的getOutputStream();getinputStream();获得写和读的方法 其余的操作就和IO流的操作一样!!
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class EchoServer {
int ccid;
public int getCcid() {
return ccid;
}
public void setCcid(int ccid) {
this.ccid = ccid;
}
//端口号
private int port=3005;
//
private ServerSocket serverSocket;
private ExecutorService executorService;
private final int POOL_SIZE = 4;
private HashMap<String, Socket> socketHashMap = new HashMap<String,Socket>();private HashMap<String,Ecc> eccHashMap = new HashMap<String,Ecc>();byte Packet_Head[]={0x4c,0x53};
byte Packet_End[]={0x0d,0x0a};
public EchoServer() throws IOException {
serverSocket = new ServerSocket(port);
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_SIZE);
System.out.println("服务器启动");
}
public void service() {
while (true) {
Socket socket=null;
try {
socket = serverSocket.accept(); //接收客户连接
//socket.setSoTimeout(10000); //10秒无数据传输,连接自动断掉
socket.setSoTimeout(100000);
executorService.execute(new Handler(socket)); //创建一个工作线程 ,加入到线程池
}catch (IOException e) {
e.printStackTrace();
}
}
}
class Handler implements Runnable{
private Socket socket;
private InputStream br;
private OutputStream pw;
private byte reciver_buffer []=new byte [2048];
private int recive_length;
boolean login_succed = false;
// int ccid;
public Handler(Socket socket){
this.socket = socket;
}
public int indexOf(byte data[],int length_a,byte b[],int length_b){
int i,j;
for(i=0;i<=(length_a-length_b);i++){
boolean isValid=true;
for(j=0;j<length_b;j++){
if(data[i+j]!=b[j]){
isValid=false;
break;
}
}
if(isValid){
return i;
}
}
return -1; }
public void run(){
Socket sendSocket =null;
Ecc ecc = new Ecc(socket);
try{
System.out.println("New connection accepted"+
socket.getInetAddress()+":"+socket.getPort());
br = socket.getInputStream();
pw = socket.getOutputStream();
while(true){
recive_length=ecc.read(reciver_buffer);
if(recive_length!=-1){
int index_head=indexOf(reciver_buffer,reciver_buffer.length,Packet_Head,Packet_Head.length);
System.out.println("packet_head index is:"+index_head);
if(index_head==-1) continue;
int index_end=indexOf(reciver_buffer,reciver_buffer.length,Packet_End,Packet_End.length);
System.out.println("packet_end index is:"+index_end);
if(index_end==-1) continue;
int recive_sum = 0xff & reciver_buffer[index_end-1];
int check_sum=0;
for (int i = 2; i < recive_length - 3; i++)
{
check_sum+=0xff & reciver_buffer[i];
}
check_sum = check_sum & 0xff;
System.out.println("recive_sum is : "+ Integer.toHexString(recive_sum));
System.out.println("check_sum is : "+ Integer.toHexString(check_sum));
if((byte)recive_sum!=(byte)check_sum) continue;
System.out.println("data packet is valid!");
int packet_cmd = 0xff & reciver_buffer[3];
int packet_cmd_reserved = 0xff & reciver_buffer[4];
int recive_valid_length = ((0xff & reciver_buffer[7])<<8)+ (0xff & reciver_buffer[6]);
int valid_data_length = 0;
byte sum=0;
switch (packet_cmd) {
case 0x7e:
ccid = 0xff & reciver_buffer[5];
System.out.println("ccid is : "+ccid);
if (ccid==0x00) {
//控制客户端登陆
if(login_succed==false){
//发登陆成功回应
valid_data_length = 0x06;
byte send_longin_ack [] = new byte[]{(byte) 0x4c,0x53,(byte)0x00,0x3f,0x00,(byte)ccid,(byte)valid_data_length,(byte)(valid_data_length>>8),
0x00,0x00,0x00,0x00,0x00,0x00,sum,0x0d,0x0a};
for(int i=0;i<send_longin_ack.length-3;i++)
sum+=0xff & send_longin_ack[i];
send_longin_ack[send_longin_ack.length-3]=(byte)sum;
ecc.write(send_longin_ack);
eccHashMap.put(""+ccid+"", ecc);
login_succed = true;
socket.setSoTimeout(0);
System.out.println("ecc id:"+ccid+" longin succeed!");
}
}
else {
//ecc登陆
if(login_succed==false){
//发登陆成功回应
//登陆成功,修改数据库状态 ccid
valid_data_length = 0x06;
byte send_longin_ack [] = new byte[]{(byte)0x4c,0x53,(byte)0x00,0x3f,0x00,(byte)ccid,(byte)valid_data_length,(byte)(valid_data_length>>8),
0x00,0x00,0x00,0x00,0x00,0x00,sum,0x0d,0x0a};
for(int i=0;i<send_longin_ack.length-3;i++)
sum+=0xff & send_longin_ack[i];
send_longin_ack[send_longin_ack.length-3]=(byte)sum;
ecc.write(send_longin_ack);
login_succed = true;
System.out.println("ecc id:"+ccid+" longin succeed!");
// ccidHashSet.add(Integer.toHexString(ccid));
socketHashMap.put(Integer.toHexString(ccid), socket);
}
}
break;
case 0x7b:
//心跳包
//发心跳回应
if(login_succed==true){
valid_data_length = 0x00; byte send_heart_ack [] = new byte[]{(byte) 0x4c,0x53,(byte)0x00,0x3e,0x00,(byte)ccid,(byte)valid_data_length,(byte)(valid_data_length>>8),
sum,0x0d,0x0a};
for(int i=0;i<send_heart_ack.length-3;i++)
sum+=0xff & send_heart_ack[i];
send_heart_ack[send_heart_ack.length-3]=(byte)sum;
ecc.write(send_heart_ack);
}
case 0x20:
//查询数据回应 ,处理并存入数据库
if (login_succed==true) {
switch (packet_cmd_reserved) {
case 0x00://正常响应
System.out.println("recive_valid_length is "+ recive_valid_length);
byte send_meter [] = new byte [recive_valid_length];
for (int i = 0; i < send_meter.length; i++) {
send_meter[i] = reciver_buffer[i+8];
}
boolean crc_check = ModbusCrc16.checkBuf(send_meter);
System.out.println("crc check is "+crc_check);
if (crc_check) {
MeterDatas meter = new MeterDatas(send_meter, ccid);
if (meter.MeterUpdate()) {
//存到数据库或者直接传给需要客户端
System.out.println("DIO is :"+(0xff & meter.DIO));
System.out.println("Ua is :"+meter.Ua);
System.out.println("Ub is :"+meter.Ub);
System.out.println("Uc is :"+meter.Uc);
System.out.println("HZ is :"+meter.Hz);
}
else {
System.out.println("meter datas parse error!");
}
}
break;
case 0x01://异常响应
System.out.println("read meter error!");
break;
default:
break;
}
}
break;
case 0xd0:
String eccidString = Integer.toString(((0xff & reciver_buffer[8])<<8)+(0xff & reciver_buffer[9]));
System.out.println("eccid is "+ eccidString);
sendSocket=socketHashMap.get(eccidString);
if (sendSocket!=null) {
OutputStream sop = sendSocket.getOutputStream();
System.out.println("sendSocket is exsitl!");
valid_data_length = 0x0b;
byte sum1=0;
byte meterAddr =(byte) (0xff & reciver_buffer[10]);
byte meterCmd = (byte)0x10;
int regStartAddr =0x21;
int regCount = 0x01;
int crcValue=0x00;
int eccid =Integer.parseInt(eccidString, 16);
byte toggleButton=0;
if ((0xff & reciver_buffer[11])==0x01) {
toggleButton =(byte)0xf0;
}
byte send_meter [] = new byte []{meterAddr,meterCmd,(byte)(regStartAddr>>8),(byte)regStartAddr,(byte)(regCount>>8),(byte)regCount,0x02,toggleButton,0x00};
ModbusCrc16 modbusCrc16 = new ModbusCrc16();
modbusCrc16.update(send_meter, send_meter.length);
crcValue=modbusCrc16.value;
byte send_control [] = new byte[]{(byte) 0x4c,0x53,(byte)0xdf,0x00,(byte)(eccid>>8),(byte)eccid,(byte)valid_data_length,(byte)(valid_data_length>>8),
meterAddr,meterCmd,(byte)(regStartAddr>>8),(byte)regStartAddr,(byte)(regCount>>8),(byte)regCount,0x02,toggleButton,0x00,(byte)crcValue,(byte)(crcValue>>8),sum1,0x0d,0x0a};
for(int i=0;i<send_control.length-3;i++)
sum1+=0xff & send_control[i];
send_control[send_control.length-3]=(byte)sum1;
sop.write(send_control, 0, send_control.length);
System.out.println("send control meter cmd finished!");
sendSocket = null;
}
else {
System.out.println("sendSocket is null!");
}
break;
default:
break;
}
}
else
break;
}
}catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(socket != null) {
login_succed=false;
// ccidHashSet.remove(Integer.toHexString(ccid));
socketHashMap.remove(Integer.toHexString(ccid));
socket.shutdownInput();
socket.shutdownOutput();
br.close();
pw.close();
socket.close();
//断开连接,修改数据库状态 ccid
}
System.out.println(socket.getInetAddress()+":"+socket.getPort()+" is closed.");
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
public static void main(String[] args)throws IOException {
// TODO Auto-generated method stub
new EchoServer().service();
}
}以上是第一个类
package com.linksprite.devices;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;public class Ecc {
private Socket m_sock;
private InputStream m_inputStream;
private OutputStream m_outputStream;
public Ecc(Socket sock)
{
m_sock = sock;
try {
m_inputStream = m_sock.getInputStream();
m_outputStream = m_sock.getOutputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public int read(byte[] buffer)
{
try {
return m_inputStream.read(buffer);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return 0;
}
}
public void write(byte[] buffer)
{
try{
m_outputStream.write(buffer);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
这是第二个类
我没明白 如何从EchoServer里面获得CCID 然后再根据需求发送给客户端指定的数据包
我没明白这个怎么写。
但是 现在的一个问题是,我要获得的CCID 得是从之前已经连接上来的客户端的线程获取。求解 应该怎么做?
没有根据交互过程进行类的封装啊。这个协议本身我都没弄明白,更别说CCID了。
至于楼主的问题,根据经验,当客户端连接到服务端之后,客户端发送特定的数据包给服务端,里面含有CCID,
服务端接收该数据包后,解析数据包,得到CCID,就OK了。
然后写了一个 public void sendMessage(byte ccid){
Ecc ecc=eccHashMap.get(ccid);
byte sendOpenLight[] = new byte[]{(byte)0x4c,0x53,ccid};
ecc.write(sendOpenLight);
}
如果我现在想测试一下这个代码,用一个软件模拟客户端发送数据包上来,然后用HashMap存入连接进来的客户端,然后我用那个sendMessage的方法获得客户端登陆连接进来的ccid,并且写入指定的数据包,在上面的这个方法中,我随意定义了一个数据包。作为测试··· 那么我写测试类 应该如何写呢?