1. 程式人生 > >有關ServerSocket服務監聽WEB專案並且進行簡單測試(入門)

有關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專案中引用這個服務,那麼資料訪問多半來自伺服器,需要一個解析資料的過程,這個方法大家百度就可以了!

感謝!