基于TCP/IP协议的socket通讯server

思路:

socket必须要随项目启动时启动,所以需用Spring自带的监听器,需要保持长连接,要用死循环,所以必须另外起线程,不能阻碍主线程运行

1.在项目的web.xml中配置listener

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.ra.car.utils.MyListener</listener-class>
</listener>

2.因为是一个独立的线程,所以需要调用的注入类不能通过@resource或@aotowire注入,需要应用上下文获取

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.0.xsd"> <!-- 扫描包加载Service实现类 -->
<context:component-scan base-package="com.ra.*.service.impl"></context:component-scan>
<bean id="DataCallBackService" class="com.ra.truck.service.impl.DataCallBackServiceImpl"/>
<bean id="RdTrackInfoService" class="com.ra.truck.service.impl.RdTrackInfoServiceImpl"/>
<bean id="OutInterfaceService" class="com.ra.truck.service.impl.OutInterfaceImpl"/>
<bean id="RdPhotoInfoService" class="com.ra.truck.service.impl.RdPhotoInfoServiceImpl"/>
<bean id="MessagePackegerService" class="com.ra.truck.service.impl.MessagePackegerServiceImpl"/>
<!--<bean id="redis" class="com.ra.redis.service.impl.JedisClientCluster"/>-->
</beans>

  

3.创建listener监听器类

package com.ra.car.utils;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.ra.car.rabbitMQ.PBWRabbitMQCustomer;
import com.ra.car.rabbitMQ.RabbitMQCustomer; /**
* listener监听器类
*
*/
public class MyListener implements ServletContextListener { protected static final Logger logge = LoggerFactory
.getLogger(MyListener.class); @Override
public void contextInitialized(ServletContextEvent arg0) {
//必须单独启线程去跑listener
Mythread myThread = new Mythread();
//创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程
// ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
// cachedThreadPool.execute(myThread);
Thread thread = new Thread(myThread);
thread.start();
//启动MQTT
// MQTTSubMsg client = new MQTTSubMsg();
// client.start();
RabbitMQCustomer customer=new RabbitMQCustomer();
Thread threadCustomer = new Thread(customer);
threadCustomer.start(); PBWRabbitMQCustomer pbwcustomer=new PBWRabbitMQCustomer();
Thread pbwT = new Thread(pbwcustomer);
pbwT.start();
} @Override
public void contextDestroyed(ServletContextEvent arg0) {
logge.info("进入ListenerUtil的contextDestroyed方法.........");
} }
package com.ra.car.utils;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /**
* 多线程类
*
*/
public class Mythread implements Runnable{ protected static final Logger logge = LoggerFactory
.getLogger(Mythread.class); @Override
public void run() {
logge.info("进入ListenerUtil的contextInitialized方法.........");
try {
ServerSocket serverSocket = new ServerSocket(8888);
logge.info("socket通信服务端已启动,等待客户端连接.......");
logge.info("我是111111111111111");
while (true) {
Socket socket = serverSocket.accept();// 侦听并接受到此套接字的连接,返回一个Socket对象
JavaTCPServer socketThread = new JavaTCPServer(socket);
socketThread.run();
try {
//休眠10毫秒,压力测试50000次连接无压力
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
logge.error("通信服务器启动失败!", e);
}
}
public static String stampToDate(String s){
Long timestamp = Long.parseLong(s)*1000;
String date = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date(timestamp)); return date;
} }
package com.ra.car.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class JavaTCPServer {
protected static final Logger logger=LoggerFactory.getLogger(JavaTCPServer.class); private Socket socket; public JavaTCPServer(Socket socket) {
this.socket = socket;
} public void run() {
MyThread2 myThread2=null;
try {
myThread2 = new MyThread2(socket);
} catch (IOException e) {
e.printStackTrace();
}
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.execute(myThread2);
} }
package com.ra.car.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ra.truck.model.RdDeviceCallBackDataDomain;
import com.ra.truck.service.DataCallBackService;
import com.ra.truck.service.RdPhotoInfoService;
import com.ra.truck.service.RdTrackInfoService;
import com.ra.truck.service.outInterface.OutInterfaceService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.ContextLoader; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.*; public class MyThread2 implements Runnable { protected static final Logger logger = LoggerFactory
.getLogger(MyThread2.class); private Socket socket;
private InputStream inputStream;
private OutputStream outputStream;
private PrintWriter printWriter; private int totalCount; //总数量 private int adasCount; // 传输的ADAS信号数量
private int gpsCount; // 传输的GPS信号数量
private DataCallBackService dataCallBackService;//数据回传private SimpleDateFormat df; public MyThread2(Socket socket) throws IOException {
this.socket = socket;
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
printWriter = new PrintWriter(outputStream); dataCallBackService=(DataCallBackService)
ContextLoader.getCurrentWebApplicationContext().getBean("DataCallBackService");
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
} @Override
public void run() {
// 根据输入输出流和客户端连接 // 得到一个输入流,接收客户端传递的信息
// InputStreamReader inputStreamReader = new InputStreamReader(
// inputStream);// 提高效率,将自己字节流转为字符流
// bufferedReader = new BufferedReader(inputStreamReader);// 加入缓冲区
Date timestart = new Date();
Date timeend = null;
long minuine = 0;
int count = 0;
while (true) {
try {
if (inputStream.available() > 0 == false) {
timeend = new Date();
minuine = timeend.getTime() - timestart.getTime();
if (minuine != 0 && (minuine / 1000) > 60) {
break;
}
continue;
} else {
timestart = new Date();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
logger.error("*****线程休眠出现异常*****", e);
}
count = inputStream.available();
byte[] b = new byte[count];
int readCount = 0; // 已经成功读取的字节的个数
while (readCount < count) {
readCount += inputStream.read(b, readCount, count
- readCount);
}
logger.info("**********当前服务器正在被连接**********");
logger.info("正在连接的客户端IP为:"
+ socket.getInetAddress().getHostAddress()); logger.info("当前时间为:" + df.format(new Date()));
String data = new String(b, "utf-8");
logger.info("传输过来的info:" + data);
String id = jsonStringToObject(data);
Map<Object, Object> map = new HashMap<Object, Object>();
//心跳发送不带id的json数据
if (StringUtils.isNotBlank(id)) {
map.put("id", id);
}
map.put("resultCode", "1");
map.put("result", "success");
printWriter.print(JSON.toJSONString(map) + "\n");
printWriter.flush();
}
} catch (Exception e) {
logger.error("数据传输出现异常", e);
try {
outputStream = socket.getOutputStream();
} catch (IOException e1) {
logger.error("获取outputStream出现异常");
}
// 获取一个输出流,向服务端发送信息
// printWriter = new PrintWriter(outputStream);// 将输出流包装成打印流
Map<Object, Object> map = new HashMap<Object, Object>();
map.put("resultCode", "0");
map.put("result", "fail");
printWriter.print(JSON.toJSONString(map) + "\n");
printWriter.flush();
}
}
try {
printWriter.close();
outputStream.close();
inputStream.close();
logger.info("30s没有发送数据,服务端主动关闭连接");
logger.info("被断开的客户端IP为:"
+ socket.getInetAddress().getHostAddress());
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
logger.info("被断开的时间为:" + df.format(new Date()));
socket.close();
} catch (IOException e) {
logger.error("关闭socket出现异常", e); } /*
* while ((temp = bufferedReader.readLine()) != null) { info += temp;
* logger.info(bufferedReader.readLine());
* logger.info("已接收到客户端连接!!!!!!"); logger.info("服务端接收到客户端信息:" +
* info + ",当前客户端ip为:" + socket.getInetAddress().getHostAddress());
* logger.info("服务端接收到客户端信息:" + info + ",当前客户端ip为:" +
* socket.getInetAddress().getHostAddress()); }
*/ /*
* logger.info("*****测试Redis*****"); JedisClient
* jedisClient=(JedisClient)
* ContextLoader.getCurrentWebApplicationContext().getBean("redis");
* jedisClient.set("testLanHao", "123456789"); String
* str=jedisClient.get("testLanHao");
* logger.info("从Redis中取得数据为:"+str);
* logger.info("*****测试Redis*****");
*/ // ApplicationContext applicationContext=new
// ClassPathXmlApplicationContext("classpath*:applicationContext-*.xml");
// RiskManageService
// riskManageService=applicationContext.getBean(RiskManageService.class);
// socket单独线程,需要重新加载上下文,扫描的类在applicationContext-service.xml配置
/*
* RiskManageService riskManageService=(RiskManageService)
* ContextLoader.getCurrentWebApplicationContext().getBean("risk");
* RdRiskEventInfo rdRiskEventInfo=new RdRiskEventInfo();
* rdRiskEventInfo.setId("10"); try { List<RdPhotoInfo>
* list=riskManageService.findPhotoInfoByEventId(rdRiskEventInfo);
* logger.info(list); } catch (ServiceException e) {
* e.printStackTrace(); }
*/
// outputStream = socket.getOutputStream();// 获取一个输出流,向服务端发送信息
// printWriter = new PrintWriter(outputStream);// 将输出流包装成打印流 } private String jsonStringToObject(String data) {
//数据解析方法return xx;
}
public static Date stampToDate(String s){ Long timestamp = Long.parseLong(s)*1000;
Date date = new Date(timestamp); return date;
}
上一篇:洛谷P2820 局域网 (最小生成树)


下一篇:IA-32 Assembly Language Reference Manual