1.配置web.xml
在xml中添加以下内容 <!--后台服务器-->
<context-param>
<param-name>SocketPort</param-name>
<param-value>30000</param-value>
</context-param>
<listener>
<description>Socket服务随web启动而启动</description>
<listener-class>com.xiaotao.socket.listener.ServerSocketListener</listener-class>
</listener>
2.编写监听 Listener 类 public class ServerSocketListener implements ServletContextListener {
private SocketThread socketThread = null;
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
ServletContext servletContext = servletContextEvent.getServletContext();
String str=(String)servletContext.getAttribute("socketThreadIsRun");
if (str == null && socketThread == null){
servletContext.setAttribute("socketThreadIsRun", "true");
socketThread = new SocketThread(null,servletContext);
socketThread.start(); // servlet上下文初始化时启动socket服务端线程
}
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
if(socketThread != null && !socketThread.isInterrupted())
{
socketThread.closeSocketServer();
socketThread.interrupt();
}
}
3.编写后台消息接收线程public class SocketThread extends Thread {
// 定义保存所有Socket的ArrayList
public static ArrayList<Socket> socketList = new ArrayList<Socket>();
// 保存socketList中每个socket的信息
public static ArrayList<SocketInfo> socketInfo = new ArrayList<SocketInfo>();
private ServerSocket serverSocket = null;
private ServletContext servletContext = null;
public SocketThread(ServerSocket serverSocket,ServletContext servletContext)
{
if(serverSocket == null)
{
try {
this.serverSocket = new ServerSocket(30000);
} catch (IOException e) {
e.printStackTrace();
}
}
this.servletContext = servletContext;
}
@Override
public void run()
{
while(!this.isInterrupted())
{
try {
// 此行代码会阻塞,将一直等待别人的连接
Socket socket = serverSocket.accept();
/* SocketInfo socketInfo1 = new SocketInfo(socket.getPort(),socket.getInetAddress());*/
// 客户端地址
System.out.println("###getInetAddress # " + socket.getInetAddress());
// 客户端端口
System.out.println("###getPort # " + socket.getPort());
socketList.add(socket);
System.out.println("###连接成功");
if(socket != null)
{
// 每当客户端连接后启动一条ServerThread线程为该客户端服务
new Thread(new OperatorSocketData(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void closeSocketServer()
{
try {
if(serverSocket != null && !serverSocket.isClosed())
{
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}4.编写请求处理 public class OperatorSocketData implements Runnable{
// 定义当前线程所处理的Socket
private Socket s = null;
// 该线程所处理的Socket所对应的输入流
private BufferedReader br = null;
public OperatorSocketData(Socket s) throws IOException {
this.s = s;
// 初始化该Socket对应的输入流
br = new BufferedReader(new InputStreamReader(s.getInputStream() , "utf-8"));
}
public void run()
{
try
{
String content = null;
// 采用循环不断从Socket中读取客户端发送过来的数据
while ((content = readFromClient()) != null)
{
System.out.println("客户端--->服务器: " + content);
System.out.println("--A-" + Arrays.toString(content.getBytes("utf-8")));
// TODO:实现客户端与服务器的一对一交流,暂未实现客户端之间的交流
// 遍历socketList中的每个Socket,
// 将读到的内容向每个Socket发送一次
// for (Iterator<Socket> it = WebServer.socketList.iterator(); it.hasNext(); )
// {
// Socket s = it.next();
try{
OutputStream os = s.getOutputStream();
os.write((content + "\r\n").getBytes("utf-8"));
System.out.println("服务器--->客户端: content + --C-- " + content);
}
catch(SocketException e)
{
e.printStackTrace();
// 删除该Socket。
// it.remove();
s.close();
System.out.println(SocketThread.socketList);
}
// }
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
// 定义读取客户端数据的方法
private String readFromClient()
{
try
{
return br.readLine();
}
// 如果捕捉到异常,表明该Socket对应的客户端已经关闭
catch (IOException e)
{
e.printStackTrace();
// 删除该Socket。
SocketThread.socketList.remove(s);
}
return null;
}
} |