本文主要介绍在web应用程序下怎么使用Socket建立连接
一:首先要新建线程监听类,负责启动一个服务端线程,在web.xml中监听
说明:本来port已经在xml文件中配置,为了方便测试修改,统一放在常量类中
<context-param>
<param-name>socketPort</param-name>
<param-value>8883</param-value>
</context-param>
<listener>
<description>Socket</description>
<listener-class>com.zlxls.socket.ServerSocketListener</listener-class>
</listener>
ServerSocketListener.java
package com.zlxls.socket;
import com.common.Constants;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* ServerSocket线程监听类,负责启动一个服务端线程
* @ClassNmae:ServerSocketListener
* @author zlx-雄雄
* @date 2017-11-13 13:27:21
*
*/
public class ServerSocketListener implements ServletContextListener{
private ServerSocketThread socketThread;
@Override
public void contextDestroyed(ServletContextEvent e){
if (socketThread != null && socketThread.isInterrupted()){
socketThread.closeServerSocket();
socketThread.interrupt();
}
}
@Override
public void contextInitialized(ServletContextEvent e){
ServletContext servletContext = e.getServletContext();
System.out.println("Socket 服务端初始化完成:Server contextInitialized over");
if (socketThread == null){
socketThread = new ServerSocketThread(Constants.port);// 从web.xml中context-param节点获取socket端口
socketThread.start();
}
}
}
二:首先本文定义相关常量:Constants.java
package com.common;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
/**
*
* 系统常量定义类-全局变量
* @ClassNmae:Constants
* @author zlx-雄雄
* @date 2017-8-16 11:42:41
*
*/
public class Constants {
/**
* Socket相关
*/
public static final String over = "over";
public static final int port = 8123;
public static final String encode = "gb2312";
public static int socketCount = 0;
public static List<Socket> socketList = new ArrayList<>();
}
三:服务端启动客户端线程操作类ServerSocketThread.java
package com.zlxls.socket;
import com.common.Constants;
import com.zlxls.util.DateUtil;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务端启动客户端线程操作类
* 负责接收客户端请求,并启动一个线程为此请求服务
* @ClassNmae:ServerSocketThread
* @author zlx-雄雄
* @date 2017-11-13 13:28:01
*
*/
public class ServerSocketThread extends Thread{
private ServerSocket serverSocket;
public ServerSocketThread(int port){
if (serverSocket == null){
try{
this.serverSocket = new ServerSocket(port);
}catch (IOException e){
e.printStackTrace();
}
}
}
@Override
public void run(){
try{
while (!this.isInterrupted()){//this.isInterrupted()方法用来检测“this”的中断状态,且不会改变线程的状态标志。
Socket socket = serverSocket.accept();
System.out.println("服务线程数量:Server SocketThread start:"+(++Constants.socketCount));
if (socket != null){
Constants.socketList.add(socket);
System.out.println("新的Socket连接:new commer:"+socket.getLocalAddress()+":"+socket.getLocalPort()+"--"+socket.getInetAddress().getHostName()+":"+socket.getRemoteSocketAddress().toString()+"--"+DateUtil.getTime());
ServerSocketReceiveThread serverSocketReceiveThread = new ServerSocketReceiveThread(socket);
serverSocketReceiveThread.start();
}
}
}catch (Exception ex){
System.out.println("SocketThread err:"+ex.getMessage());
}
}
public void closeServerSocket(){
try{
if (serverSocket != null && !serverSocket.isClosed()){
serverSocket.close();
}
System.out.println("SocketThread close");
}catch (Exception ex){
System.out.println("SocketThread err:"+ex.getMessage());
}
}
}
四:服务端消息处理线程ServerSocketReceiveThread.java
package com.zlxls.socket;
import com.common.Constants;
import com.zlxls.util.DateUtil;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import com.alibaba.fastjson.JSONObject;
/**
* 服务端消息处理线程
* 包括接收客户端消息,并且返回消息给客户端
* 将消息解析为json,用作处理
* @ClassNmae:ServerSocketReceiveThread
* @author zlx-雄雄
* @date 2017-11-13 16:58:38
*
*/
public class ServerSocketReceiveThread extends Thread{
private final Socket socket;
public ServerSocketReceiveThread(Socket socket){
this.socket = socket;
}
@Override
public void run(){
BufferedReader bufferedReader = null;
PrintWriter printWriter = null;
try{
//获取客户端传入信息
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(),Constants.encode));
//得到客户端输出流
printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), Constants.encode));
int count = 0;
while (true){
String cmdmsg = bufferedReader.readLine();
//如果为空,表示当前连接已经关闭,客户端即是是空字符串,这里也不会为null
if(cmdmsg==null) {
System.out.println("已关闭--新的Socket连接:new commer:"+socket.getLocalAddress()+":"+socket.getLocalPort()+"--"+socket.getInetAddress().getHostName()+":"+socket.getRemoteSocketAddress().toString()+"--"+DateUtil.getTime());
Constants.socketCount--;
Constants.socketList.remove(socket);
break;
}
/**
* 将消息解析为json进行处理
* ...
*/
String time = DateUtil.getTime();
//打印客户端信息
System.out.println(time+":服务接收:Server received:现在是与"+socket.getRemoteSocketAddress().toString()+"第["+(++count)+"]次会话--消息内容:【" + cmdmsg+"】");
//将信息返回给客服端
printWriter.println(socket.getRemoteSocketAddress().toString()+"你好,现在是第["+count+"]次会话--"+time+",服务端已经收到你的消息:【"+cmdmsg+"】");
printWriter.flush();
/**
* 这个在服务端其实没有作用
* 前端请求连接关闭后,传回来的消息是null,因此只要判断消息为null,就可以说明客户端已经关闭了连接
*/
if (cmdmsg.equals(Constants.over)) break;
}
bufferedReader.close();
printWriter.close();
socket.close();
}catch (IOException ex){
ex.printStackTrace();
}
}
}
五:客户端SocketClient.java
package com.zlxls.socket;
import com.common.Constants;
import com.zlxls.util.DateUtil;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
/**
* SocketClient客户端,负责发送请求和消息
* @ClassNmae:SocketClient
* @author zlx-雄雄
* @date 2017-11-11 9:55:39
*
*/
public class SocketClient {
public static void main(String args[]) {
Socket socket;
PrintWriter printWriter;
BufferedReader bufferedReader;
BufferedReader bufferedReaderFromServer;
try{
socket=new Socket("127.0.0.1",Constants.port);
String str="请输入消息内容:";
System.out.print(str);
//获取输入流
bufferedReader=new BufferedReader(new InputStreamReader(System.in, Constants.encode));
//读取输入信息
String readline=bufferedReader.readLine();
//获取输出流,将信息输出到服务端
printWriter=new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), Constants.encode));
//获取输入流,取得服务端返回信息
bufferedReaderFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream(),Constants.encode));
while(!readline.equals(Constants.over)){
//将输入流获取信息发送给服务端
printWriter.println(readline);
printWriter.flush();
//输出输入流信息
System.out.println(DateUtil.getTime()+"--Client:"+readline);
//输出服务端返回信息
System.out.println(DateUtil.getTime()+"--Server:"+bufferedReaderFromServer.readLine());
//循环读取
System.out.print(str);
readline=bufferedReader.readLine();
}
printWriter.close();
bufferedReader.close();
bufferedReaderFromServer.close();
socket.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}