java socket服务端通讯 循环读取 使用线程

调用方式:

public class DemoApplication {

    public static void main(String[] args) {

        SocketServer socketServer = new SocketServer();
        socketServer.start();

//        SpringApplication.run(DemoApplication.class, args);
    }

}

 

 

介绍:

(1)SocketServer的run方法用来接收socket连接,调用socketHandle.run

(2)SocketHandle的run方法用来处理socket的输入输出流,调用SocketHandle.handle

(3)SocketHandle的handle静态方法用来处理用户输入的字符串,可以调用自定义的处理方法

 

另:

SocketHandle的run方法在128行给了3种输入流处理方式,越后面越好,但要客户端配合。

 

SocketServer.java:

// 文件名  SocketServer.java

package com.example.demo;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SocketServer extends Thread {

    int port = 34560;
    int nThreads = 100;

    public void service() {
        this.run();
    }

    @Override
    public void run(){
        ExecutorService threadPool = null;
        ServerSocket server = null;
        try{
            // 监听指定的端口
            server = new ServerSocket(port);
            // server将一直等待连接的到来
            System.out.println("server将一直等待连接的到来");
            System.out.println("");
            //如果使用多线程,那就需要线程池,防止并发过高时创建过多线程耗尽资源
            threadPool = Executors.newFixedThreadPool(nThreads);

            while (true) {
                Socket socket = null;
                try{
                    socket = server.accept();
                }catch(Exception e){
                    e.printStackTrace();
                    if(socket!=null){socket.close();}
                }

                System.out.println("获得连接");

                SocketHandle socketHandle = new SocketHandle(socket);
                threadPool.submit(socketHandle);
            }

        } catch(Exception e){
            System.out.println("获取socket,异常错误:");
            System.out.println(e.toString());
            e.printStackTrace();
            System.out.println("");
        } finally {
            if(server!=null){
                try {
                    server.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(threadPool!=null){
                threadPool.shutdown();
            }
        }

    }
}



class SocketHandle implements Runnable {

//    String charsetName = "UTF-8";
    String charsetName = "GBK";
    int socketSoTimeout = 5 * 60 * 1000;  // 毫秒单位

    Socket socket;

    SocketHandle(Socket socket){
        this.socket = socket;
    }

    public int 序号值 = 0;
    public String 获得序号(){
        if (序号值 > 50000){
            序号值 = 0;
        }
        ++序号值;
        return Integer.toString(序号值) + ": ";
    }

    @Override
    public void run(){
        // 建立好连接后,从socket中获取输入输出流,并建立缓冲区进行读取写入
        InputStream inputStream = null;
        OutputStream outputStream = null;
        BufferedReader reader = null;
        BufferedWriter writer = null;
        try {
            inputStream = socket.getInputStream();
            outputStream = socket.getOutputStream();
            reader=new BufferedReader(new InputStreamReader(inputStream,charsetName));
            writer=new BufferedWriter(new OutputStreamWriter(new BufferedOutputStream(outputStream),charsetName));

            // 设定最长 接收数据间隔时间
            socket.setSoTimeout(socketSoTimeout);

            byte[] bytes = new byte[102400];
            int len;
            String line;

            while(true){

                // 这个socket状态判断,是本地状态判断,无法得知远端状态
                if(socket != null && socket.isBound() && !socket.isClosed() && socket.isConnected()&& !socket.isInputShutdown() && !socket.isOutputShutdown()) {

                }else{
                    System.out.println("socket不可用,准备断开连接");
                    break;
                }

//                try{
//                    socket.sendUrgentData(0);
//                }catch (Exception e){
//                    System.out.println("发送紧急包失败,准备断开连接");
//                    break;
//                }


                // -- 数据读取方式
                // (1)直接读取方式
                len = inputStream.read(bytes);
                if(len == -1){
                    break;
                }
                line = new String(bytes, 0, len, charsetName);
                System.out.println(获得序号() + "收到了信息:" + line);
                String rst_str = SocketHandle.handle(line);
                System.out.println("返回:" + rst_str);

                if(rst_str!=null && !(rst_str.trim().replaceAll("\\s*|\t|\r|\n", "").isEmpty())) {
                    rst_str += "\r\n";
                    writer.write(rst_str);
                    writer.flush();
                }


                // (2)换行结尾方式
//                line = reader.readLine();
//                if(line != null){
//                    System.out.println(获得序号() + "收到了信息:" + line);
//                    String rst_str = SocketHandle.handle(line);
//                    System.out.println("返回:" + rst_str);
//                    if(rst_str!=null && !(rst_str.trim().replaceAll("\\s*|\t|\r|\n", "").isEmpty())) {
//                        rst_str += "\r\n";
//                        writer.write(rst_str);
//                        writer.flush();
//                    }
//                }else{
//                    break;
//                }


                // (3)约定长度方式
                // 首先读取两个字节表示的长度
//                int first = inputStream.read();
//                //如果读取的值为-1 说明到了流的末尾,Socket已经被关闭了,此时将不能再去读取
//                if(first==-1){
//                    break;
//                }
//                int second = inputStream.read();
//                int length = (first << 8) + second;
//
//                StringBuilder sb = new StringBuilder();
//                int readLength=0;
//                while(readLength<length){
//                    int read = inputStream.read(bytes, readLength, length-readLength);
//                    readLength+=read;
//                    // 注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
//                    sb.append(new String(bytes, 0, read, charsetName));
//                }
//                line = sb.toString();
//                System.out.println(获得序号() + "收到了信息:" + line);
//                String rst_str = SocketHandle.handle(line);
//                System.out.println("返回:" + rst_str);
//                if(rst_str!=null && !(rst_str.trim().replaceAll("\\s*|\t|\r|\n", "").isEmpty())) {
//                    String message = rst_str;
//                    // 首先需要计算得知消息的长度
//                    byte[] sendBytes = message.getBytes(charsetName);
//                    // 然后将消息的长度优先发送出去
//                    outputStream.write(sendBytes.length >>8);
//                    outputStream.write(sendBytes.length);
//                    // 再将剩下的消息发送出去
//                    outputStream.write(sendBytes);
//                    outputStream.flush();
//                }
                
            }

        } catch (Exception e) {
            // 意料中有两种错误,读超时 和 连接重置
            System.out.println("处理socket,异常错误:");
//                        e.printStackTrace();
            System.out.println(e.toString());
        } finally {
            System.out.println("关闭连接");
            System.out.println("");

            try {
                if(reader!=null)
                    reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                if(writer!=null)
                    writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                if(inputStream!=null)
                    inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                if(outputStream!=null)
                    outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                if(socket!=null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static String handle(String input_str){
        String rst_str = null;
        try{

            rst_str = "hello world";

        } catch(Exception e){
            System.out.println("处理用户输入,异常错误:");
            System.out.println(e.toString());
            System.out.println("");

            rst_str = null;
        } finally {

        }

        return rst_str;
    }

}

 

 

 

 

用来测试的client端:

SocketClient.java

// 文件名 SocketClient.java

package com.example.demo;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class SocketClient {

    public static void main(String[] args) throws Exception{

        // 要连接的服务端IP地址和端口
        String host = "127.0.0.1";
        int port = 34560;
        String charsetName = "GBK";
        // 与服务端建立连接
        Socket socket = new Socket(host, port);
        // 建立连接后获得输出流
        OutputStream outputStream = socket.getOutputStream();
        InputStream inputStream = socket.getInputStream();

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedReader reader=new BufferedReader(new InputStreamReader(inputStream,charsetName));

        while(true){
            System.out.println("请输入数据:");
            String message = br.readLine();
//            message += "\r\n";
            outputStream.write(message.getBytes(charsetName));
            outputStream.flush();


            String sb = reader.readLine();
            System.out.println("get message from server: " + sb);

            System.out.println("");
        }

//        br.close();
//        reader.close();
//        inputStream.close();
//        outputStream.close();
//        socket.close();

    }
}

 

 

效果:

 

 

源文件:

蓝奏云  https://wws.lanzous.com/iM7I7fmdt5e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值