首先呢,题目是瞎写的,我希望尽可能让看到这篇文章的人知道我干了个啥(虽然仔细想想我也不知道我干了个啥)!
背景是:最近正好看到Socket这方面的东西,以前也没仔细接触过,也就大学时候学过一个简单的JAVA 利用Socket写一个简单的client/server聊天室,后来也就在没用过,最近看到有个ServerSocket的东西,适用于监听端口,用于Socket与HTTP之间的通信云云。
废话不多说,我先讲讲我的思路,毕竟就像博文首页写的那样,是一个JAVA萌新的进阶之旅,所以如果有哪里不对或者理解错误的,希望各位大牛能给我指出来,或者告诉我正确的思路,感激不尽。
正文:
1.建立一个WEB项目(因为后期是要在WEB项目中用的,所以先试试)。搭建好,随便写个页面能访问就OK了,没必要仔细弄,结构对就行;
2.在WEB项目中的web.xml文件中加入监听标签:
<!-- 引入自定义的Socket监听类-->
<listener>
<listener-class>com.sxzbxc.scoket.test.SocketServiceLoader</listener-class>
</listener>
3.既然要自定义监听了,创建一个监听类是无可厚非的:
package com.sxzbxc.scoket.test;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* 将socket service随tomcat启动
*/
public class SocketServiceLoader implements ServletContextListener {
// socket server 线程
private SocketThread socketThread;
@Override
public void contextDestroyed(ServletContextEvent arg0) {
if (null != socketThread && !socketThread.isInterrupted()) {
socketThread.closeSocketServer();
socketThread.interrupt();
}
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
// TODO Auto-generated method stub
if (null == socketThread) {
// 新建线程类
socketThread = new SocketThread(null);
// 启动线程
socketThread.start();
}
}
}
自定义的监听类需要实现ServletContextListener这个接口,并且重写两个方法,一个是初始化contextInitialized,一个是销毁contextDestroyed。如上图。
4.其中都需要创建线程的方法。所以我们需要在写一个创建线程的类:
package com.sxzbxc.scoket.test;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* socket 线程类
*
*/
public class SocketThread extends Thread {
private ServerSocket serverSocket = null;
public SocketThread(ServerSocket serverScoket) {
try {
if (null == serverSocket) {
//绑定和监听端口
this.serverSocket = new ServerSocket(4700);
System.out.println("ServerSocket服务启动!绑定端口为4700");
System.out.println("socket start");
}
} catch (Exception e) {
System.out.println("SocketThread创建socket服务出错");
e.printStackTrace();
}
}
public void run() {
while (!this.isInterrupted()) {
try {
Socket socket = serverSocket.accept();
if (null != socket && !socket.isClosed()) {
// 处理接受的数据
new SocketOperate(socket).start();
}
socket.setSoTimeout(30000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void closeSocketServer() {
try {
if (null != serverSocket && !serverSocket.isClosed()) {
serverSocket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
5.接下来我们看到run方法中用到了多线程处理数据的一个线程:SocketOperate这个类,继续:
package com.sxzbxc.scoket.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.servlet.ServletContext;
/**
* 多线程处理socket接收的数据
*
*/
public class SocketOperate extends Thread {
private Socket socket;
public SocketOperate(Socket socket) {
this.socket = socket;
}
@SuppressWarnings("unused")
public void run() {
try {
System.out.println("scoket创建成功");
InputStream in = socket.getInputStream();
PrintWriter out = new PrintWriter(socket.getOutputStream());
// BufferedReader wt = new BufferedReader(new
// InputStreamReader(System.in));
while (true) {
// 读取客户端发送的信息
String strXML = "";
byte[] temp = new byte[1024];
int length = 0;
while ((length = in.read(temp)) != -1) {
strXML += new String(temp, 0, length);
}
if ("end".equals(strXML)) {
System.out.println("准备关闭socket");
break;
}
if ("".equals(strXML))
continue;
System.out.println("客户端发来:" + strXML.toString());
out.flush();
out.close();
}
socket.close();
System.out.println("socket stop.....");
} catch (IOException ex) {
} finally {
}
}
}
这样,一个简单的ServerSocket的多线程就创建好了,但是我如何才能知道我写的是否生效呢,还需要找个东西测试一下,在此之前大家记得看,上边我绑定和监听的端口是4700(这个端口只要没有被占用就可以)。
启动Tomcat,控制台已经输出:
ServerSocket服务启动!绑定端口为4700
socket start
这说明基本编程问题是没有错的,现在就看能否成功监听该端口的信息;
网页上直接输入"localhost:4700",在控制台我收到的如下信息:
scoket创建成功
scoket创建成功
客户端发来:GET / HTTP/1.1
Host: localhost:4700
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: _ga=GA1.1.1927822800.1509517125
这说明服务是可以监听到的该端口的,但是我想知道,如果是一个Clinet的发送来信息,是否也可以监听到呢?于是写了一个向固定IP和端口发数据的类,主要是为了模拟,所以创建一个XML文件,配置上IP和端口:
<?xml version="1.0" encoding="UTF-8"?>
<!-- XML文件,配置服务器IP和端口 -->
<config>
<server>
<url>localhost</url>
<port>4700</port>
</server>
</config>
顺便一个读取配置的类:
package com.sxzbxc.scoket.test;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
public class ReadServerXML {
public String getUrl (){
String url = null;
Configuration config;
try {
config = new XMLConfiguration("SocketServer.xml");
url = config.getString("server.url");
} catch (ConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return url;
}
public Integer getPort(){
Integer port = null;
try{
Configuration config = new XMLConfiguration("SocketServer.xml");
port = Integer.valueOf(config.getString("server.port"));
}catch(ConfigurationException e){
e.printStackTrace();
}
return port;
}
}
接下来就是一个模拟Clinet类了:
package com.sxzbxc.scoket.test;
import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.*;
public class Send {
public static void main(String[] args) throws Exception {
ReadServerXML readServerXML = new ReadServerXML();
String url = readServerXML.getUrl();
Integer port = readServerXML.getPort();
Socket socket = new Socket(url, port);
// 向服务器端程序发送数据
OutputStream outputStream = socket.getOutputStream();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
bufferedWriter.write("you know ,life's like movie ?");
bufferedWriter.flush();
bufferedWriter.close();
socket.close();
System.out.println("finish send data!!");
}
}
运行该方法后:tomcat控制台输出:
scoket创建成功
客户端发来:you know ,life's like movie ?
本地JAVA Application控制台输出:
finish send data!!
验证成功:说明只要是发往服务器这个端口的信息,都会被获取到
后面的内容其实跑题了,我们需要在WEB项目中引用这个服务,那么数据访问多半来自服务器,需要一个解析数据的过程,这个方法大家百度就可以了!
感谢!