Socket编程(基于web应用程序)

本文主要介绍在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();
        }
    }  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

生命无须向死而生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值