http://www.oschina.net/code/snippet_2507499_53892

 [代码]servlet监听器中同时启动serversocket服务端    

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.safe.listener;
 
import java.io.IOException;
import java.net.ServerSocket;
 
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
 
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
 
import tcp.thread.ServerThread;
import tcp.util.TCPConstant;
 
import com.safe.service.CenterService;
 
public class InitListener implements ServletContextListener {
     
     ServerSocket server;
 
     @Override
     public void contextInitialized(ServletContextEvent event) {
         System.out.println( "web应用初始化:初始化的位置:启动ServerSocket的地方" );
         // 获取Spring容器以及service层对象
         ServletContext servletContext = event.getServletContext();
         WebApplicationContext ctx = WebApplicationContextUtils
                 .getWebApplicationContext(servletContext);
         for ( int i = 0 ; i < ctx.getBeanDefinitionNames().length; i++) {
             System.out.println(ctx.getBeanDefinitionNames()[i]);
         }
         CenterService service = (CenterService) ctx
                 .getBean( "centerServiceImpl" );
 
         // 启动serverSocket
         try {
             server = new ServerSocket(TCPConstant.SERVER_PORT);
             new Thread( new ServerThread(server, service)).start();
             System.out.println( "一个TCPThreadForServer 的run执行完毕" );
         } catch (IOException e) {
             System.out.println( "初始化serverSocket 报错" );
             e.printStackTrace();
         }
     }
 
     @Override
     public void contextDestroyed(ServletContextEvent sce) {
         System.out.println( "web应用销毁 " );
         try {
             if ( null != server) {
                 System.out.println( "关闭ServerSocket" );
                 server.close();
             }
         } catch (IOException e) {
             e.printStackTrace();
         }
 
     }
}

2. [代码]serversocket线程    

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package tcp.thread;
 
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
 
import java.util.Hashtable;
 
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
 
import org.apache.log4j.Logger;
 
import tcp.framer.Frame;
 
import com.safe.service.CenterService;
 
/**
  * 每个套接字ServerSocket为一个线程,不然tomcat会阻塞等待socket客户端连接
  *
  * @author yh
  *
  */
public class ServerThread implements Runnable {
     private static Logger logger = Logger.getLogger(HandingClientThread. class );
 
     public static final Map<String, ConcurrentLinkedQueue<Frame>> queueMap = new Hashtable<String, ConcurrentLinkedQueue<Frame>>();
 
     private ServerSocket server;
     private CenterService service;
 
     public ServerThread() {
         super ();
     }
 
     public ServerThread(ServerSocket server, CenterService service) {
         super ();
         this .server = server;
         this .service = service;
     }
 
     // public void closeServer() throws IOException {
     // if (null != server) {
     // System.out.println("closeServer():关闭server");
     // server.close();
     // }
     // }
 
     @Override
     public void run() {
         Socket client = null ;
         try {
             while (!server.isClosed()) {
                 logger.info( "serverthread.run():服务器开启,等待客户端访问....." );
                 client = server.accept();
                 System.out.println( "为什么这次debug要点两次才能直接跑过去" );
                 logger.info(
                         "添加新的客户端socket:" + client + client.getInetAddress().getHostAddress() + ":" + client.getPort());
                 new Thread( new HandingClientThread(client, service), "HandingClientThread" ).start();
             }
         } catch (IOException e) {
             logger.info( "服务器启动失败!" );
             e.printStackTrace();
         } finally {
             try {
                 if (client != null ) {
                     client.close();
                 }
                 if (server != null ) {
                     server.close();
                     logger.info( "服务器关闭!" );
                 }
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     }
}

3. [代码]为每一个客户端处理请求或发送    

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
package tcp.thread;
 
import java.io.IOException;
 
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
 
import org.apache.log4j.Logger;
 
import tcp.coder.MsgCoder;
import tcp.framer.Frame;
import tcp.framer.LengthFramer;
import tcp.msg.M_p_AlarmStatus;
import tcp.msg.M_p_Pant;
import tcp.msg.M_p_PeopleInfo;
import tcp.msg.M_q_GetPeopleInfo;
import tcp.msg.M_q_HandingAlarm;
import tcp.msg.M_q_Pant;
import tcp.msg.PoliceTask;
import tcp.thread.son.WriteThread;
import tcp.util.MsgUtil;
import tcp.util.TCPConstant;
 
import com.safe.model.Police;
import com.safe.model.User;
import com.safe.service.CenterService;
import com.safe.util.ConstantUtil;
import com.safe.util.DateUtil;
 
/**
  * 每个访客一个线程
  *
  * @author yh
  *
  */
// @Component
public class HandingClientThread implements Runnable {
     private static Logger logger = Logger.getLogger(HandingClientThread. class );
 
     private Socket client;
     private CenterService service;
 
     public HandingClientThread() {
         super ();
     }
 
     public HandingClientThread(Socket client, CenterService service) {
         super ();
         this .client = client;
         this .service = service;
     }
 
     public Socket getClient() {
         return client;
     }
 
     public void setClient(Socket client) {
         this .client = client;
     }
 
     @Override
     public void run() {
         /** 添加发送队列到全局 */
         String outListKey = client.getInetAddress().getHostAddress() + ":" + client.getPort();
         ConcurrentLinkedQueue<Frame> writeQueue = new ConcurrentLinkedQueue<Frame>();
         ServerThread.queueMap.put(outListKey, writeQueue);
         logger.info(
                 "TCP服务端clientTread:有一个客户端socket连接到服务端:ServerThread.queueMap.size():" + ServerThread.queueMap.size());
 
         // 成帧器 需要传给每个线程用来读取或写入帧
         LengthFramer framer = null ;
         try {
             client.setKeepAlive( true );
             client.setSoTimeout( 60 * 1000 ); // 这个方法表示
                                             // 超时就报异常并断开读取连接,但是还可以向客户端发送.如有异常在读取位置抛出
             framer = new LengthFramer(client, "【服务端】" );
         } catch (SocketException e) {
 
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         }
 
     
         logger.info( "线程WriteThread启动" );
         new Thread( new WriteThread(framer, writeQueue, service, client), "WriteThread" ).start();
 
         /*** 接受消息 并将响应结果放入写出队列 */
         try {
             while ( true ) {
                 Frame reqFrame;
                 reqFrame = framer.nextFrame();
                 Frame rspFrame = null ;
                 int msgType = reqFrame.getMsgType();
                 switch (msgType) {
                 /** 一 收到心跳 */
                 case TCPConstant.MSGTYPE_Q_PANT:
                     M_q_Pant m_q_Pant = new MsgCoder<M_q_Pant>().readFrame(reqFrame, M_q_Pant. class );
                     System.out.println( "【服务端】<AC 心跳请求:" + m_q_Pant);
                     // 响应心跳
                     M_p_Pant p_Pant = new M_p_Pant();
                     rspFrame = new MsgCoder<M_p_Pant>().readMsg(p_Pant);
 
                     break ;
                 /** 二 获取人物信息请求 */
                 case TCPConstant.MSGTYPE_Q_PEOPLEINFO:
                     M_q_GetPeopleInfo q_GetPeopleMsg = new MsgCoder<M_q_GetPeopleInfo>().readFrame(reqFrame,
                             M_q_GetPeopleInfo. class );
                     System.out.println( "【服务端】<AC 查人请求:" + q_GetPeopleMsg);
                     byte peopleType = q_GetPeopleMsg.getType();
                     if (TCPConstant.PEOPLETYPE_POLICE == peopleType) { // 警员
                         Police police = service.getPoliceByPoliceNo(q_GetPeopleMsg.getID().trim());
                         String birthdayStr = DateUtil.fmtDateToStr(police.getDetails().getBirthday(), "yyyy-MM-dd" );
 
                         rspFrame = new MsgCoder<M_p_PeopleInfo>().readMsg(
                                 new M_p_PeopleInfo(police.getPoliceNo(), peopleType, police.getDetails().getName(),
                                         birthdayStr, police.getDetails().getTel(), police.getDetails().getAddress(),
                                         police.getDetails().getShenFenId(), police.getDetails().getPhoto()));
 
                     } else if (TCPConstant.PEOPLETYPE_USER == peopleType) { // 用户
                         User user = service.getUserByLoginName(q_GetPeopleMsg.getID().trim());
                         String birthdayStr = DateUtil.fmtDateToStr(user.getDetails().getBirthday(), "yyyy-MM-dd" );
                         rspFrame = new MsgCoder<M_p_PeopleInfo>().readMsg(
                                 new M_p_PeopleInfo(user.getLoginName(), peopleType, user.getDetails().getName(),
                                         birthdayStr, user.getDetails().getTel(), user.getDetails().getAddress(),
                                         user.getDetails().getShenFenId(), user.getDetails().getPhoto()));
 
                     }
                     break ;
                 /** 三 处理报警请求(派警或者标记假警等) */
                 case TCPConstant.MSGTYPE_Q_HANDINGALARM:
                     // 解析请求消息
                     M_q_HandingAlarm q_handingMsg = new MsgCoder<M_q_HandingAlarm>().readFrame(reqFrame,
                             M_q_HandingAlarm. class );
                     System.out.println( "【服务端】《AC 处理报警请求:" + q_handingMsg);
 
                     // 操作派警
                     int alarmId = q_handingMsg.getEventID();
                     byte type = q_handingMsg.getType();
 
                     if (type == ConstantUtil.ALARM_TYPE_TRUE) { // 真警则派发任务
                         String taskContent = q_handingMsg.getTaskInfo();
                         // 派发任务
                         List<PoliceTask> policeTasks = q_handingMsg.getTask();
                         List<String> policeNos = new ArrayList<String>();
                         for (PoliceTask policeTask : policeTasks) {
                             policeNos.add(policeTask.getPoliceID());
                         }
                         // service.sendTaskAndNotice(alarmId, policeNos,
                         // taskContent);// TODO 避免报别名不存在错误 暂时注释
                     } else { // 不是真警 则修改对应类型 1假警 2重复报警
                         service.updateAlarmType(alarmId, type);
                     }
                     // 发送处理报警的响应消息()这个应该由警员提交任务时触发?并在提交任务的action中启动新线程连接对方再发送
                     // AlarmInfo alarmInfo=service.getAlarmById(alarmId);
                     // TODO 假数据
                     M_p_AlarmStatus msg = new M_p_AlarmStatus(alarmId, ( byte ) 1 );
                     Frame pMsgframe = new MsgCoder<M_p_AlarmStatus>().readMsg(msg);
                     // 添加到写出队列(所有)
                     MsgUtil.addFrametoAllQueueMap(pMsgframe);
                     break ;
                 default :
                     logger.warn( "AcceptRequestThread 未知的请求!~" );
                     break ;
                 }
                 if (rspFrame != null ) {
                     writeQueue.add(rspFrame);
                 }
             }
         } catch (IOException e) {
             logger.error( "服务端 读取失败,结束读取线程" , e);
         } finally {
             ServerThread.queueMap.remove(client.getInetAddress().getHostAddress() + ":" + client.getPort());
             try {
                 client.shutdownInput();
                 client.shutdownOutput();
                 client.close();
                 logger.error( "关闭客户端连接" );
             } catch (IOException e1) {
                 e1.printStackTrace();
             }
 
         }
 
     }
 
}

4. [代码]循环写出到输出流线程    

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
package tcp.thread.son;
 
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
 
import org.apache.log4j.Logger;
 
import com.safe.model.Police;
import com.safe.model.User;
import com.safe.service.CenterService;
 
import tcp.coder.MsgCoder;
import tcp.framer.Frame;
import tcp.framer.LengthFramer;
import tcp.msg.M_p_Alarm;
import tcp.msg.M_p_PoliceCoordFlow;
import tcp.msg.M_p_UserCoordFlow;
import tcp.msg.PoliceCoord;
import tcp.msg.UserCoord;
import tcp.thread.ServerThread;
import tcp.util.MyListUtil;
import tcp.util.TCPConstant;
 
/**
  * 位置流
  *
  * @author sh
  *
  */
public class WriteThread implements Runnable {
     private static Logger logger = Logger.getLogger(WriteThread. class );
     private LengthFramer framer;
     private ConcurrentLinkedQueue<Frame> writeQueue; // 当前连接的写出队列
     private CenterService service;
     private Socket client;
 
     public WriteThread(LengthFramer framer,
             ConcurrentLinkedQueue<Frame> writeQueue, CenterService service,
             Socket client) {
         super ();
         this .framer = framer;
         this .service = service;
         this .writeQueue = writeQueue;
         this .client = client;
     }
 
     @Override
     public void run() {
         logger.info( "进入线程WriteThread" );
 
         long lastTime_onlinePolice = System.currentTimeMillis(); // 上次发送时间 在线警员
         long lastTime_hotPolice = System.currentTimeMillis(); // 上次发送时间 忙碌警员
         long lastTime_aroundPolice = System.currentTimeMillis(); // 上次发送时间 事发周围警员
         long lastTime_hotUser = System.currentTimeMillis(); // 上次发送时间 报警人
 
         long lastTime_alarm = System.currentTimeMillis(); // 上次发送时间 报警人
         try {
             while ( true ) {
                 /** 发送输出队列中的帧 */
                 Frame frame = writeQueue.poll();
                 if (frame != null ) {
                     framer.outFrame(frame);
                 }
 
                 /** 位置流 */
                 // 所有在线警员坐标流
                 if (System.currentTimeMillis() - lastTime_onlinePolice > TCPConstant.INTERVAL_ONLINEPOLICE * 1000 ) {
                     List<M_p_PoliceCoordFlow> policeCoordFlowMsgList = getPoliceCoordFlowMsgsByPoliceList(
                             service.getOnlinePoliceList(),
                             TCPConstant.MAXCOUNT_POLICECOORDS);
                     for (M_p_PoliceCoordFlow policeCoordFlow : policeCoordFlowMsgList) {
                         Frame policeCoord_frame = new MsgCoder<M_p_PoliceCoordFlow>()
                                 .readMsg(policeCoordFlow);
 
                         framer.outFrame(policeCoord_frame);
 
                     }
                     lastTime_onlinePolice = System.currentTimeMillis();
                 }
                 // 忙碌警员 坐标流
                 if (System.currentTimeMillis() - lastTime_hotPolice > TCPConstant.INTERVAL_HOTPOLICE * 1000 ) {
                     List<M_p_PoliceCoordFlow> policeCoordFlowMsgList = getPoliceCoordFlowMsgsByPoliceList(
                             service.getHotPoliceList(),
                             TCPConstant.MAXCOUNT_POLICECOORDS);
                     for (M_p_PoliceCoordFlow policeCoordFlow : policeCoordFlowMsgList) {
                         Frame policeCoord_frame = new MsgCoder<M_p_PoliceCoordFlow>()
                                 .readMsg(policeCoordFlow);
 
                         framer.outFrame(policeCoord_frame);
 
                     }
                     lastTime_hotPolice = System.currentTimeMillis();
                 }
                 // 事发周围警员 坐标流
                 if (System.currentTimeMillis() - lastTime_aroundPolice > TCPConstant.INTERVAL_AROUNDPOLICE * 1000 ) {
                     List<M_p_PoliceCoordFlow> policeCoordFlowMsgList = getPoliceCoordFlowMsgsByPoliceList(
                             service.getAllAroundPoliceList(),
                             TCPConstant.MAXCOUNT_POLICECOORDS);
                     for (M_p_PoliceCoordFlow policeCoordFlow : policeCoordFlowMsgList) {
                         Frame policeCoord_frame = new MsgCoder<M_p_PoliceCoordFlow>()
                                 .readMsg(policeCoordFlow);
 
                         framer.outFrame(policeCoord_frame);
 
                     }
                     lastTime_aroundPolice = System.currentTimeMillis();
                 }
 
                 // 报警人坐标流
                 if (System.currentTimeMillis() - lastTime_hotUser > TCPConstant.INTERVAL_HOTUSER * 1000 ) {
                     List<M_p_UserCoordFlow> userCoordFlowMsgList = getUserCoordFlowMsgsByUserList(
                             service.getHotUserList(),
                             TCPConstant.MAXCOUNT_USERCOORDS);
                     for (M_p_UserCoordFlow userCoordFlow : userCoordFlowMsgList) {
                         Frame userCoordframe = new MsgCoder<M_p_UserCoordFlow>()
                                 .readMsg(userCoordFlow);
 
                         framer.outFrame(userCoordframe);
 
                     }
                     lastTime_hotUser = System.currentTimeMillis();
                 }
 
                 /** 临时测试发送报警 */
                 if (System.currentTimeMillis() - lastTime_alarm > 20 * 1000 ) {
                     M_p_Alarm amMsg = new M_p_Alarm( 99 , "userID" ,
                             110.110110110 , 91.1911911 ,
                             System.currentTimeMillis(), "jspAdress" );
                     Frame alarmFrame = new MsgCoder<M_p_Alarm>().readMsg(amMsg);
                     framer.outFrame(alarmFrame);
                     lastTime_alarm = System.currentTimeMillis();
                 }
 
             }
         } catch (IOException e) {
             logger.error( "服务端 写出失败,结束写出线程" , e);
         } finally {
             ServerThread.queueMap.remove(client.getInetAddress()
                     .getHostAddress() + ":" + client.getPort());
             try {
                 client.shutdownInput();
                 client.shutdownOutput();
                 client.close();
             } catch (IOException e1) {
                 e1.printStackTrace();
             }
 
         }
 
     }
 
     /**
      * 通过警员集合和指定消息包容量 获得警员位置流消息集合
      *
      * @param policeList
      * @param maxcountPolicecoords
      * @return
      */
     private List<M_p_PoliceCoordFlow> getPoliceCoordFlowMsgsByPoliceList(
             List<Police> policeList, int maxcountPolicecoords) {
         List<M_p_PoliceCoordFlow> msgList = new ArrayList<M_p_PoliceCoordFlow>();
         // 将处在报警状态的用户集合按照 单个分包消息的最大量分割为多个子集合并组成双层集合返回
         List<List<Police>> bilayerPoliceList = MyListUtil.splitList(policeList,
                 maxcountPolicecoords);
         /** 如果处在报警状态的用户数量超过一定值则分包发送 */
         for (List<Police> sonPoliceList : bilayerPoliceList) {
             List<PoliceCoord> policeCoordList = new ArrayList<PoliceCoord>();
             for (Police police : sonPoliceList) {
                 int alarmId = 0 ;
                 if ( null != police.getCurrTask()) {
                     System.out.println( "PoliceCoordsThread,该警员有当前任务" );
                     alarmId = police.getCurrTask().getAlarmInfo().getId();
                 }
                 PoliceCoord policeCoord = new PoliceCoord(police.getPoliceNo(),
                         alarmId, police.getCoord().getX(), police.getCoord()
                                 .getY());
                 policeCoordList.add(policeCoord);
             }
             M_p_PoliceCoordFlow msg = new M_p_PoliceCoordFlow(
                     policeCoordList.size(), policeCoordList);
             msgList.add(msg);
         }
         return msgList;
     }
 
     /**
      * 通过用户集合和指定消息包容量 获得用户位置流消息集合
      *
      * @param userList
      * @param maxCountUsercoords
      * @return
      */
     private List<M_p_UserCoordFlow> getUserCoordFlowMsgsByUserList(
             List<User> userList, int maxCountUsercoords) {
         List<M_p_UserCoordFlow> msgList = new ArrayList<M_p_UserCoordFlow>();
         // 将处在报警状态的用户集合按照 单个分包消息的最大量分割为多个子集合并组成双层集合返回
         List<List<User>> bilayerUserList = MyListUtil.splitList(userList,
                 maxCountUsercoords);
         /** 如果处在报警状态的用户数量超过一定值则分包发送 */
         for (List<User> sonUserList : bilayerUserList) {
             List<UserCoord> userCoordList = new ArrayList<UserCoord>();
             for (User user : sonUserList) {
                 UserCoord userCoord = new UserCoord(user.getLoginName(), user
                         .getCoord().getX(), user.getCoord().getY());
 
                 userCoordList.add(userCoord);
             }
             M_p_UserCoordFlow msg = new M_p_UserCoordFlow(userCoordList.size(),
                     userCoordList);
             msgList.add(msg);
         }
         return msgList;
     }
}

5. [代码]协议消息工具类,添加消息到所有消息列表,以便群发    

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package tcp.util;
 
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
 
import tcp.framer.Frame;
import tcp.thread.ServerThread;
 
public class MsgUtil {
     // 添加到写出队列(所有)
     public static  void addFrametoAllQueueMap(Frame pMsgframe) {
         Iterator<ConcurrentLinkedQueue<Frame>> values = ServerThread.queueMap.values()
                 .iterator();
         while (values.hasNext()) {
             ConcurrentLinkedQueue<Frame> writeQueue = values.next();
             writeQueue.offer(pMsgframe); // 给所有的连接的队列加上这个帧数据
         }
 
     }
}

6. [代码]字节工具类,将基本类型转换为字节数组(大端),再以16进制字符串返回    

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package tcp.util;
 
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
 
public class MyByteUtil_DataStream {
     // 返回大字节序的字节数组
     public static byte [] int2byteArray( int i) throws IOException {
         ByteArrayOutputStream byteStream = null ;
         DataOutputStream out = null ;
         byte [] bytes = null ;
         try {
             byteStream = new ByteArrayOutputStream();
             out = new DataOutputStream(byteStream);
             out.writeInt(i);
             out.flush();
             bytes = byteStream.toByteArray();
         } finally {
             byteStream.close();
             out.close();
         }
         return bytes;
     }
 
     // 返回大字节序的字节数组
     public static byte [] short2byteArray( short s) throws IOException {
         ByteArrayOutputStream byteStream = null ;
         DataOutputStream out = null ;
         byte [] bytes = null ;
         try {
             byteStream = new ByteArrayOutputStream();
             out = new DataOutputStream(byteStream);
             out.writeShort(s);
             out.flush();
             bytes = byteStream.toByteArray();
         } finally {
             byteStream.close();
             out.close();
         }
         return bytes;
     }
 
     // 返回大字节序的字节数组
     public static byte [] String2byteArray(String s) throws IOException {
         ByteArrayOutputStream byteStream = null ;
         DataOutputStream out = null ;
         byte [] bytes = null ;
         try {
             byteStream = new ByteArrayOutputStream();
             out = new DataOutputStream(byteStream);
             out.writeChars(s);
             out.flush();
             bytes = byteStream.toByteArray();
         } finally {
             byteStream.close();
             out.close();
         }
         return bytes;
     }
 
     // 字节数组转换为16进制数组并以字符串返回
     public static String byteArrayToHex( byte [] bs) {
         char [] chars = "0123456789ABCDEF" .toCharArray();
         StringBuilder sb = new StringBuilder( "" );
 
         int bit;
 
         for ( int i = 0 ; i < bs.length; i++) {
             bit = (bs[i] & 0x0f0 ) >> 4 ;
             sb.append(chars[bit]);
             bit = bs[i] & 0x0f ;
             sb.append(chars[bit]);
             sb.append( ' ' );
         }
         return sb.toString().trim();
 
     }
 
     public static void main(String[] args) throws IOException {
         System.out.println(byteArrayToHex(String2byteArray( "" )));
         System.out.println(byteArrayToHex(String2byteArray( " " )));
         System.out.println(Arrays.toString(int2byteArray( 1 )));
         System.out.println( "[]"
                 + MyByteUtil_DataStream.byteArrayToHex(MyByteUtil_DataStream
                         .short2byteArray(( short ) 55 ))
                 + " "
                 + MyByteUtil_DataStream.byteArrayToHex(MyByteUtil_DataStream
                         .short2byteArray(( short ) 1234 ))
                 + " "
                 + MyByteUtil_DataStream.byteArrayToHex(MyByteUtil_DataStream
                         .int2byteArray( 1121 ))
                 + " "
                 + MyByteUtil_DataStream.byteArrayToHex(MyByteUtil_DataStream
                         .String2byteArray( "sdasdsadasd" )));
     }
}

7. [代码]分割list 的工具类,将一个list按照指定大小分割为多个,返回    

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package tcp.util;
 
import java.util.ArrayList;
import java.util.List;
 
public class MyListUtil {
     public static <T> List<List<T>> splitList(List<T> list, int pageSize) {
         List<List<T>> listArray = new ArrayList<List<T>>();
 
         ArrayList<T> al = new ArrayList<T>();
         for (T x : list) {
             al.add(x);
             if (pageSize == al.size()) {
                 listArray.add(al);
                 al = new ArrayList<T>();
             }
         }
 
         if ( 0 != al.size())
             listArray.add(al);
 
         return listArray;
     }
}

8. [代码]编码解码器使用了泛型,不用为每种消息写一个编码器    

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package tcp.coder;
 
import java.util.ArrayList;
import java.util.List;
 
import org.apache.log4j.Logger;
 
import com.google.gson.Gson;
 
import tcp.framer.Frame;
import tcp.framer.LengthFramer;
import tcp.msg.BaseMsg;
import tcp.msg.M_p_Alarm;
import tcp.msg.M_p_AlarmStatus;
import tcp.msg.M_p_Pant;
import tcp.msg.M_p_PeopleInfo;
import tcp.msg.M_p_PoliceCoordFlow;
import tcp.msg.M_p_RequestSupport;
import tcp.msg.M_p_UserCoordFlow;
import tcp.msg.M_q_GetPeopleInfo;
import tcp.msg.M_q_HandingAlarm;
import tcp.msg.M_q_Pant;
import tcp.msg.PoliceTask;
import tcp.util.TCPConstant;
 
public class MsgCoder<M extends BaseMsg> {
     private static Logger logger = Logger.getLogger(LengthFramer. class );
 
     /**
      * 将消息解析为帧
      *
      * @param msg
      * @return
      */
     public Frame readMsg(M msg) {
         String msgJson = null ;
         int msgType = getMsgTypeByMsgClass(msg);
         short length = TCPConstant.MSGHEAD_LENGTH;
         if (msgType != TCPConstant.MSGTYPE_Q_PANT && msgType != 0 ) { // 如果不是心跳请求——唯一没有消息体的包
             msgJson = new Gson().toJson(msg);
             length = ( short ) (length + msgJson.length() * 2 );
             // length = (short) (length +
             // msgJson.getBytes(TCPConstant.NET_STRCODE).length - 2);//
             // -2表示减去unicode码的BOM
             // } catch (UnsupportedEncodingException e) {
             // logger.error("将字符串转换为字节数组(为取得字节长度) 错误", e);
             // e.printStackTrace();
 
         }
 
         Frame frame = new Frame(length, TCPConstant.CHECKCODE, msgType, msgJson);
         return frame;
     };
 
     /**
      * 将帧解析为消息
      *
      * @param frame
      * @return
      */
     public M readFrame(Frame frame, Class<M> c) {
         String msgJson = frame.getMsgJson();
         M m = new Gson().fromJson(msgJson, c);
         return m;
     };
 
     private int getMsgTypeByMsgClass(M msg) {
         if (msg instanceof M_q_Pant) {
             return TCPConstant.MSGTYPE_Q_PANT;
         } else if (msg instanceof M_p_Pant) {
             return TCPConstant.MSGTYPE_P_PANT;
         } else if (msg instanceof M_p_Alarm) {
             return TCPConstant.MSGTYPE_P_ALARM;
         } else if (msg instanceof M_p_UserCoordFlow) {
             return TCPConstant.MSGTYPE_P_USERCOORD;
         } else if (msg instanceof M_p_PoliceCoordFlow) {
             return TCPConstant.MSGTYPE_P_POLICECOORD;
         } else if (msg instanceof M_q_GetPeopleInfo) {
             return TCPConstant.MSGTYPE_Q_PEOPLEINFO;
         } else if (msg instanceof M_p_PeopleInfo) {
             return TCPConstant.MSGTYPE_P_PEOPLEINFO;
         } else if (msg instanceof M_q_HandingAlarm) {
             return TCPConstant.MSGTYPE_Q_HANDINGALARM;
         } else if (msg instanceof M_p_AlarmStatus) {
             return TCPConstant.MSGTYPE_P_HANDINGALARM;
         } else if (msg instanceof M_p_RequestSupport) {
             return TCPConstant.MSGTYPE_P_REQUESTSUPPORT;
         } else {
             System.out.println( "msg类型错误" );
         }
 
         return 0 ;
     }
 
     public static void main(String[] args) {
         MsgCoder<M_q_HandingAlarm> coder1 = new MsgCoder<M_q_HandingAlarm>();
         PoliceTask task = new PoliceTask( "" );
         List<PoliceTask> tasks = new ArrayList<PoliceTask>();
         tasks.add(task);
         M_q_HandingAlarm q_HandingMsg = new M_q_HandingAlarm( 1 , ( byte ) 1 , 1 , "" , tasks);
         int i = coder1.getMsgTypeByMsgClass(q_HandingMsg);
         System.out.println(i);
         System.out.println(TCPConstant.MSGTYPE_Q_HANDINGALARM);
 
         Frame q_HandingFrame = coder1.readMsg(q_HandingMsg);
         System.out.println(q_HandingFrame);
         M_q_HandingAlarm de_q_HandingMsg = coder1.readFrame(q_HandingFrame, M_q_HandingAlarm. class );
         System.out.println(de_q_HandingMsg);
 
         MsgCoder<M_q_Pant> coder2 = new MsgCoder<M_q_Pant>();
         M_q_Pant q_PantMsg = new M_q_Pant();
         int j = coder2.getMsgTypeByMsgClass(q_PantMsg);
         System.out.println(j);
         System.out.println(TCPConstant.MSGTYPE_Q_PANT);
 
         Frame q_PantMsgFrame = coder2.readMsg(q_PantMsg);
         System.out.println(q_PantMsgFrame);
         M_q_Pant de_q_PantMsg = coder2.readFrame(q_PantMsgFrame, M_q_Pant. class );
         System.out.println(de_q_PantMsg);
     }
}

9. [代码]帧的处理类,从输入流读取,和向输出流发送    

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package tcp.framer;
 
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
 
import org.apache.log4j.Logger;
 
import tcp.util.MyByteUtil_DataStream;
import tcp.util.TCPConstant;
 
public class LengthFramer {
     private static Logger logger = Logger.getLogger(LengthFramer. class );
 
     private Socket socket;
     private DataInputStream in; // wrapper for data I/O
     private DataOutputStream out;
 
     private String shenFen;
 
     // 构造器,获取帧消息源的输入流,并将其包裹在一个 DataInputStream 中。
     public LengthFramer(Socket socket, String shenFen) throws IOException {
         this .socket = socket;
         this .in = new DataInputStream(socket.getInputStream());
         this .out = new DataOutputStream(socket.getOutputStream());
         this .shenFen = shenFen;
     }
 
     public Socket getSocket() {
         return socket;
     }
 
     /**
      * 发送一帧
      *
      * @param frame
      * @throws IOException
      */
     public void outFrame(Frame frame) throws IOException {
 
         short length = frame.getLength();
         if (length > Short.MAX_VALUE) {
             throw new IOException( "message too long" );
 
         }
 
         short checkCode = frame.getCheckCode();
         int msgType = frame.getMsgType();
         String msgJson = frame.getMsgJson();
         logger.info(shenFen + "[编码并发送outFrame():]" + frame);
         logger.info(shenFen + "[HexArray]"
                 + MyByteUtil_DataStream.byteArrayToHex(MyByteUtil_DataStream.short2byteArray(length)) + " "
                 + MyByteUtil_DataStream.byteArrayToHex(MyByteUtil_DataStream.short2byteArray(checkCode)) + " "
                 + MyByteUtil_DataStream.byteArrayToHex(MyByteUtil_DataStream.int2byteArray(msgType)) + " "
                 + MyByteUtil_DataStream
                         .byteArrayToHex(MyByteUtil_DataStream.String2byteArray(msgJson == null ? "" : msgJson)));
 
         out.writeShort(length);
         out.writeShort(checkCode);
         out.writeInt(msgType);
         // 输出消息数据
         if (msgJson != null && ! "" .equals(msgJson)) {
             out.writeChars(msgJson);
         }
         out.flush();
 
     }
 
     /**
      * 读入一帧
      *
      * @return
      * @throws IOException
      */
     public Frame nextFrame() throws IOException {
         Frame frame = null ;
         short length = in.readShort();
         short checkcode = in.readShort();
         int msgType = in.readInt();
         // 读取指定数量的字节的消息体
         int msgLen = length - TCPConstant.MSGHEAD_LENGTH;
         String msgJson = null ;
         if (msgLen != 0 ) {
             byte [] msgBytes = new byte [msgLen];
             in.readFully(msgBytes); // readfully() 将阻塞等待,直到接收到足够的字节来填满指定的数组.
                                     // // if
             // exception, it's a framing error.
             msgJson = new String(msgBytes, TCPConstant.NET_STRCODE);
         }
         frame = new Frame(length, checkcode, msgType, msgJson);
         logger.info(shenFen + "[读取并解码 nextFrame():]" + frame);
         logger.info(shenFen + "[HexByteArray]"
                 + MyByteUtil_DataStream.byteArrayToHex(MyByteUtil_DataStream.short2byteArray(length)) + " "
                 + MyByteUtil_DataStream.byteArrayToHex(MyByteUtil_DataStream.short2byteArray(checkcode)) + " "
                 + MyByteUtil_DataStream.byteArrayToHex(MyByteUtil_DataStream.int2byteArray(msgType)) + " "
                 + MyByteUtil_DataStream
                         .byteArrayToHex(MyByteUtil_DataStream.String2byteArray(msgJson == null ? "" : msgJson)));
 
         return frame;
     }
 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块主要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此微信小程序医院挂号预约系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。微信小程序医院挂号预约系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,医生信息管理,医院信息管理,科室信息管理,预约信息管理,预约取消管理,留言板,系统管理。微信小程序用户可以注册登录,查看医院信息,查看医生信息,查看公告资讯,在科室信息里面进行预约,也可以取消预约。微信小程序医院挂号预约系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值