Java Web項(xiàng)目中使用Socket通信多線(xiàn)程、長(zhǎng)連接的方法
很多時(shí)候在javaweb項(xiàng)目中我們需要用到Socket通信來(lái)實(shí)現(xiàn)功能,在web中使用Socket我們需要建立一個(gè)監(jiān)聽(tīng)程序,在程序啟動(dòng)時(shí),啟動(dòng)socket監(jiān)聽(tīng)。我們的應(yīng)用場(chǎng)景是在java項(xiàng)目中,需要外接如一個(gè)硬件設(shè)備,通過(guò)tcp通信,獲取設(shè)備傳上來(lái)的數(shù)據(jù),并對(duì)數(shù)據(jù)做回應(yīng)。
先看一下web的監(jiān)聽(tīng)代碼:
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class AttendSocetListener implements ServletContextListener{
private SocketThread socketThread;
public void contextDestroyed(ServletContextEvent arg) {
if(null!=socketThread && !socketThread.isInterrupted())
{
socketThread.closeSocketServer();
socketThread.interrupt();
}
}
@Override
public void contextInitialized(ServletContextEvent arg) {
// TODO Auto-generated method stub
if(null==socketThread)
{
//新建線(xiàn)程類(lèi)
socketThread=new SocketThread(null);
//啟動(dòng)線(xiàn)程
socketThread.start();
}
}
}
創(chuàng)建線(xiàn)程:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class SocketThread extends Thread
{
private ServerSocket serverSocket = null;
public SocketThread(ServerSocket serverScoket){
try {
if(null == serverSocket){
this.serverSocket = new ServerSocket();
System.out.println("socket start");
}
} catch (Exception e) {
System.out.println("SocketThread創(chuàng)建socket服務(wù)出錯(cuò)");
e.printStackTrace();
}
}
public void run(){
while(true){
try {
if(serverSocket==null){
break;
}else if(serverSocket.isClosed()){
break;
}
Socket socket = serverSocket.accept();
if(null != socket && !socket.isClosed()){
//處理接受的數(shù)據(jù)
Thread t = new Thread(new SocketOperate(socket));
t.start();
}else{
break;
}
}catch (Exception e) {
System.out.println("SocketThread創(chuàng)建socket服務(wù)出錯(cuò)");
e.printStackTrace();
}
}
}
public void closeSocketServer(){
try {
if(null!=serverSocket && !serverSocket.isClosed())
{
serverSocket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
處理接受到的數(shù)據(jù):
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class SocketOperate implements Runnable {
private Socket socket;
//該線(xiàn)程所處理的Socket所對(duì)應(yīng)的輸入流
BufferedReader br = null;
String str = null;
String content = null;
InputStreamReader reader=null;
public SocketOperate(Socket socket) throws IOException
{
this.socket = socket;
reader = new InputStreamReader(this.socket.getInputStream(),"utf-");
br = new BufferedReader(reader);
}
@Override
public void run()
{
try
{
// 采用循環(huán)不斷從Socket中讀取客戶(hù)端發(fā)送過(guò)來(lái)的數(shù)據(jù)
while (true)
{
content = readFromClient();
System.out.println(content);
if (content == null)
{
break;
}
OutputStream os = socket.getOutputStream();
os.write(("RES, OK,<年班,小明>, ,#" + "\n").getBytes("utf-"));
os.flush();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
//定義讀取客戶(hù)端數(shù)據(jù)的方法
private String readFromClient()
{
try
{
str = br.readLine();
return str;
}
//如果捕捉到異常,表明該Socket對(duì)應(yīng)的客戶(hù)端已經(jīng)關(guān)閉
catch (IOException e)
{
try {
br.close();
reader.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
}
客戶(hù)端代碼:
package
import java.io.*;
import java.net.*;
public class TalkClient {
public static void main(String args[]) throws UnknownHostException, IOException {
Socket socket=new Socket("...",);
PrintWriter os=new PrintWriter(socket.getOutputStream());
BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
int i=;
while(socket.isConnected()){
os.print("BEAT,,,,.,,#"+"\n");
os.flush();
System.out.println("Client:"+i);
System.out.println("Server:"+is.readLine());
i++;
}
//繼續(xù)循環(huán)
os.close(); //關(guān)閉Socket輸出流
is.close(); //關(guān)閉Socket輸入流
socket.close(); //關(guān)閉Socket
}
}
以上所述是小編給大家介紹的Java Web項(xiàng)目中使用Socket通信多線(xiàn)程、長(zhǎng)連接的方法,希望對(duì)大家有所幫助!
相關(guān)文章
詳解Java?二叉樹(shù)的實(shí)現(xiàn)和遍歷
二叉樹(shù)可以簡(jiǎn)單理解為對(duì)于一個(gè)節(jié)點(diǎn)來(lái)說(shuō),最多擁有一個(gè)上級(jí)節(jié)點(diǎn),同時(shí)最多具備左右兩個(gè)下級(jí)節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)。本文將詳細(xì)介紹一下Java中二叉樹(shù)的實(shí)現(xiàn)和遍歷,需要的可以參考一下2022-01-01
SpringBoot整合RabbitMQ實(shí)現(xiàn)延遲隊(duì)列和死信隊(duì)列
RabbitMQ的死信隊(duì)列用于接收其他隊(duì)列中的“死信”消息,所謂“死信”,是指滿(mǎn)足一定條件而無(wú)法被消費(fèi)者正確處理的消息,死信隊(duì)列通常與RabbitMQ的延遲隊(duì)列一起使用,本文給大家介紹了SpringBoot整合RabbitMQ實(shí)現(xiàn)延遲隊(duì)列和死信隊(duì)列,需要的朋友可以參考下2024-06-06
詳解Java多線(xiàn)程編程中互斥鎖ReentrantLock類(lèi)的用法
Java多線(xiàn)程并發(fā)的程序中使用互斥鎖有synchronized和ReentrantLock兩種方式,這里我們來(lái)詳解Java多線(xiàn)程編程中互斥鎖ReentrantLock類(lèi)的用法:2016-07-07
使用log4j2打印mybatis的sql執(zhí)行日志方式
這篇文章主要介紹了使用log4j2打印mybatis的sql執(zhí)行日志方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09
Java之不通過(guò)構(gòu)造函數(shù)創(chuàng)建一個(gè)對(duì)象問(wèn)題
這篇文章主要介紹了Java之不通過(guò)構(gòu)造函數(shù)創(chuàng)建一個(gè)對(duì)象問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
spring boot 常見(jiàn)http請(qǐng)求url參數(shù)獲取方法
這篇文章主要介紹了spring boot 常見(jiàn)http請(qǐng)求url參數(shù)獲取,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
Java實(shí)現(xiàn)動(dòng)態(tài)日歷效果
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)動(dòng)態(tài)日歷效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07
Java并發(fā)編程之詳解ConcurrentHashMap類(lèi)
在之前的文章中已經(jīng)為大家介紹了java并發(fā)編程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、BlockingDeque接口,本文為系列文章第八篇.需要的朋友可以參考下2021-06-06

