有關ServerSocket服務監聽WEB專案並且進行簡單測試(入門)
首先呢,題目是瞎寫的,我希望儘可能讓看到這篇文章的人知道我幹了個啥(雖然仔細想想我也不知道我幹了個啥)!
背景是:最近正好看到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專案中引用這個服務,那麼資料訪問多半來自伺服器,需要一個解析資料的過程,這個方法大家百度就可以了!
感謝!