Socket编程

来源:互联网 发布:复旦大学梁永安知乎 编辑:程序博客网 时间:2024/06/03 20:03

socket服务器接收客户端传来的byte数组,并进行,相应的解析验证,最后用JDBC插入到数据库,相关代码如下

1.。服务端

package com.dr.SocketServer;import java.util.ArrayList;import java.util.List;import java.io.BufferedInputStream;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import java.sql.SQLException;import java.sql.Timestamp;import java.util.Date;import javax.servlet.http.HttpServlet;import org.apache.log4j.Logger;import com.dr.common.DBHelper;public class EchoServer1 implements Runnable {/** *  */private static final long serialVersionUID = 1L;/** * @param args */private static List<String> insert_info_list;// 测试数据static byte[] tmp1 = { 0x01, (byte) 0xA4, 0x31, 0x74, 0x10, 0x21, 0x60,0x00, 0x08, 0x34, 0x6D, 0x10, 0x21, 0x4E, 0x06, (byte) 0xDE, 0x22,(byte) 0xD8, (byte) 0xB7, 0x61, 0x02, 0x76, 0x5F, (byte) 0xF0,0x06, 0x00, (byte) 0xA0, 0x48, (byte) 0xC0, 0x05, 0x00, 0x06, 0x10,0x24, 0x00, 0x1A, (byte) 0xBD, 0x0B, 0x12, 0x10, 0x31, 0x00, 0x00,0x0F, 0x06, 0x10, 0x24, 0x00, 0x00, 0x00, (byte) 0xF0, 0x64, 0x00,0x00, (byte) 0xB4, 0x10, 0x30, (byte) 0x95, 0x29, (byte) 0xC6,0x31, 0x04 };private static final Logger log = Logger.getLogger(EchoServer1.class);public static void main(String[] args) {EchoServer1 e = new EchoServer1();Thread td = new Thread(e);td.start();}/********************************************************************** * 函数名称:run 功能:线程运行主函数。 参数:null 返回:null 作者:wty 编辑时间:20120828 * ********************************************************************/public void run() {ServerSocket server = null;//PrintStream out = null;BufferedInputStream buf = null;byte[] tmp = new byte[1024];//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Socket client = null;try {server = new ServerSocket(86);while (true) {// 监听socketclient = server.accept();System.out.println("有客户端连接");//out = new PrintStream(client.getOutputStream());buf = new BufferedInputStream(client.getInputStream());while (true) {// 读取socket数据buf.read(tmp);System.out.println("接收数据:" + tmp);// 判断接收数据开始位置if (tmp[0] != 0x01) {log.info(bytetostring(tmp));break;}// 判断结束数据指令if (tmp[2] != 0x31) {log.info(bytetostring(tmp));break;}// CRC校验// byte[] newByte = subBytes(tmp, 1, tmp.length - 4);// String crc = crcTable(newByte);// String crcRe = result.substring(result.length() - 4,// result.length() - 2);// if (crc != crcRe) {// log.info(bytetostring(tmp));// break;// }// 解析指令ProcessMessage(tmp);// 数据入库insertOrder();// 调用接口// 打印数据处理日志log.info(bytetostring(tmp));break;}break;// out.close();// buf.close();// client.close();}} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}/********************************************************************** * 函数名称:subBytes 功能:按位置取子bytes。 参数:原始byte数组,begin起始位置,count長度 返回:子bytes 作者: * 编辑时间:20120828 * ********************************************************************/public byte[] subBytes(byte[] src, int begin, int count) {byte[] bs = new byte[count];for (int i = begin; i < begin + count; i++)bs[i - begin] = src[i];return bs;}/********************************************************************** * 函数名称:bytetostring 功能:将byte类型数据转换为16进制字符串形式。 参数:原始byte数组 返回:转换后的16进制字符串 * 作者:wty 编辑时间:20120828 * ********************************************************************/public String bytetostring(byte[] src_bytes) {String byte_string = "";for (int i = 0; i < src_bytes.length; i++) {if (src_bytes[i] != 0) {byte_string += Integer.toString((src_bytes[i] & 0xff) + 0x100,16).substring(1)+ " ";if (src_bytes[i] == 0x04) {break;}}}byte_string = byte_string.toUpperCase();return byte_string;}/********************************************************************** * 函数名称:insertOrder 功能:将解析后的设备信息存储到数据库 参数:NULL 返回:null 作者: 编辑时间:20120828 * ********************************************************************/public int insertOrder() throws Exception {java.sql.PreparedStatement ps = null;java.sql.ResultSet rs = null;java.sql.Connection conn = null;Date d = new Date();// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");try {conn = DBHelper.getConn();ps = conn.prepareStatement("insert into orderinfo (orderid, EQUIPMENTID,LATITUDE,LONGITUDE,SPEED,state, curtime) values(?, ?, ?,?,?,?,?)");Long seq_order_info = getAminList();ps.setLong(1, seq_order_info);ps.setLong(2, Integer.parseInt(insert_info_list.get(0)));ps.setLong(3, Integer.parseInt(insert_info_list.get(2)));ps.setLong(4, Integer.parseInt(insert_info_list.get(3)));ps.setLong(5, Integer.parseInt(insert_info_list.get(4)));ps.setLong(6, 0);ps.setTimestamp(7, new Timestamp(d.getTime()));System.out.print(ps);ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();return 0;} finally {DBHelper.closeAll(rs, ps, conn);}return 1;}/********************************************************************** * 函数名称:getAminList 功能:获取order_info的序列。 参数:NULL 返回:null 作者: 编辑时间:20120828 * ********************************************************************/public Long getAminList() {java.sql.PreparedStatement ps = null;java.sql.ResultSet rs = null;java.sql.Connection conn = null;conn = DBHelper.getConn();Long n = 0L;String sql = "select seq_orderinfo.nextval from dual";try {ps = conn.prepareStatement(sql);rs = ps.executeQuery();while (rs.next()) {n = rs.getLong(1);}return n;} catch (SQLException e) {e.printStackTrace();}return n;}/********************************************************************** * 函数名称:crcTable 功能:CRC16计算程序 参数:原始bytes 返回:crc值 作者: 编辑时间:20120828 * ********************************************************************/public static String crcTable(byte[] bytes) {int[] table = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280,0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481,0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81,0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880,0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81,0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80,0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680,0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081,0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281,0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480,0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80,0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881,0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80,0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81,0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681,0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080,0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281,0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480,0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80,0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881,0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80,0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81,0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681,0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080,0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280,0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481,0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81,0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880,0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81,0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80,0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680,0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081,0x4040, };int crc = 0xffff; // 初始化crc值for (byte b : bytes) {crc = (crc >>> 8) ^ table[(crc ^ b) & 0xff];}return Integer.toHexString(crc);}/********************************************************************** * 函数名称:ProcessMessage 功能:设备数据信息解析程序 参数:原始设备数据bytes 返回: null 作者: * 编辑时间:20120828 * ********************************************************************/public static void ProcessMessage(byte[] tmp) {byte[] temp = new byte[1024];byte[] temp1 = new byte[4];// 清理掩码信息temp = updatemarks(tmp);insert_info_list = new ArrayList<String>();// 解析設備IDfor (int i = 0; i < 4; i++) {temp1[i] = temp[i + 3];}Integer driver_id = Integer.valueOf(getINTFromByte(temp1));insert_info_list.add(0, driver_id.toString());// 解析日期temp1 = new byte[4];for (int i = 0; i < 4; i++) {temp1[i] = temp[i + 11];}Integer date_number = Integer.valueOf(getINTFromByte(temp1));insert_info_list.add(1, date_number.toString());// 解析經度temp1 = new byte[4];for (int i = 0; i < 4; i++) {temp1[i] = temp[i + 15];}Integer latitude = Integer.valueOf(getINTFromByte(temp1));insert_info_list.add(2, latitude.toString());// 解析緯度temp1 = new byte[4];for (int i = 0; i < 4; i++) {temp1[i] = temp[i + 19];}Integer longitude = Integer.valueOf(getINTFromByte(temp1));insert_info_list.add(3, longitude.toString());// 解析速度temp1 = new byte[10];for (int i = 0; i < 1; i++) {temp1[i] = temp[i + 27];}Integer speed = Integer.valueOf(temp1[0]);insert_info_list.add(4, speed.toString());}/********************************************************************** * 函数名称:updatemarks 功能:处理数据中掩码信息 参数:原始设备数据bytes 返回: null 作者: 编辑时间:20120828 * ********************************************************************/public static byte[] updatemarks(byte[] tmp) {byte[] temp = new byte[1024];int j = 0;for (int i = 0; i < tmp.length; i++) {if (tmp[i] == 0x10) {switch (tmp[i + 1]) {case 0x21:temp[i - j] = 0x01;break;case 0x24:temp[i - j] = 0x04;break;case 0x30:temp[i - j] = 0x10;break;case 0x31:temp[i - j] = 0x11;break;case 0x33:temp[i - j] = 0x13;break;}i++;j++;} else {temp[i - j] = tmp[i];}}String result = "";for (int i = 0; i < temp.length; i++) {result += Integer.toString((temp[i] & 0xff) + 0x100, 16).substring(1)+ " ";}System.out.println(result);return temp;}/********************************************************************** * 函数名称:getINTFromByte 功能:将4自己byte转换为int类型 注:该函数转换的byte是低字节再前。 参数:原始bytes * 返回: 转换后的int类型数据 作者: 编辑时间:20120828 * ********************************************************************/public static int getINTFromByte(byte[] buffer) {int a = 0;a = (0xff000000 & (((int) buffer[3]) << 24) | 0x00ff0000& (((int) buffer[2]) << 16) | 0x0000ff00& (((int) buffer[1]) << 8) | 0x000000ff & (((int) buffer[0]) << 0));return a;}}


2.测试的客户端

package com.dr.SocketServer;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.Socket;import java.net.UnknownHostException;public class EchoClient {/** * @param args * @throws IOException  * @throws UnknownHostException  */public static void main(String[] args) throws UnknownHostException, IOException {// TODO Auto-generated method stub         Socket client = null;         BufferedReader buf = null;         PrintStream out = null;         //System.out.println("准备连接服务器");       // client = new Socket("121.52.216.217",86);         client = new Socket("localhost",86);         buf = new BufferedReader(new InputStreamReader(client.getInputStream()));         /*System.out.println(buf.readLine());         System.out.println(buf.readLine());*/         BufferedReader in = new BufferedReader(new InputStreamReader(System.in));                  String userInput = null;         out = new PrintStream(client.getOutputStream());                byte[] b ={         0x01, (byte)0xA4, 0x31, 0x74, 0x10, 0x21, 0x60, 0x00, 0x08, 0x34, 0x6D, 0x10, 0x21, 0x4E, 0x06, (byte)0xDE,          0x22, (byte)0xD8, (byte)0xB7, 0x61, 0x02, 0x76, 0x5F, (byte)0xF0, 0x06, 0x00, (byte)0xA0, 0x48, (byte)0xC0, 0x05, 0x00, 0x06,          0x10, 0x24, 0x00, 0x1A, (byte)0xBD, 0x0B, 0x12, 0x10, 0x31, 0x00, 0x00, 0x0F, 0x06, 0x10, 0x24, 0x00,          0x00, 0x00, (byte)0xF0, 0x64, 0x00, 0x00, (byte)0xB4, 0x10, 0x30, (byte)0x95, 0x29, (byte)0xC6, 0x31, 0x04         };         while((userInput = in.readLine())!=null){         String str="";  
    //转化为16进制,在当地看,传过去的还是在控制台直接输入的               for (int i=0;i<userInput.length();i++)                 {                 int ch = (int)userInput.charAt(i);                 String s4 = Integer.toHexString(ch);                 str = str + s4;                 }             out.println(userInput);         System.out.println(str);         }         out.close();         in.close();         client.close();                  }}