• java socket server接收并返回数据


      在上章(java socket套接字编程入门)中,服务端只能处理一次,accept()是一种阻塞状态,因此它只能同时处理一个请求,其它的请求只能排队等待前面的处理完成。

    为了支持多任务同时处理的能力,首先不要让主服务运行完成即结束,而是一种死循环的方式,让一直等待接收,其次,处理数据的需要另开线程进行,即socket的生命周期置于新开线程中。

      先定义SocketHandler作为线程单独处理socket。

    public class SocketHandler implements Runnable {
    
        private Socket socket;
    
        SocketHandler(Socket socket) {
            this.socket = socket;
        }
    
        @Override
        public void run() {
            BufferedReader bufferedReader = null;
            PrintWriter writer = null;
            try {
                System.out.println("thread:	" + Thread.currentThread().getName() );
                bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
           //true,表示自动刷新,不需要人为触发 writer
    = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true); String userInput; while ((userInput = bufferedReader.readLine()) != null) { if ("exit".equals(userInput)) { System.out.println("退出连接通信 "); break; } System.out.println("接收内容: " + userInput); String result = "服务器时间:" + LocalDateTime.now() +" " + new StringBuilder(userInput).reverse(); writer.println(result); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (writer != null) writer.close(); if (bufferedReader != null) bufferedReader.close(); socket.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } } }

    server服务端:

    public static void main(String[] args) throws IOException {
            ServerSocket serverSocket = new ServerSocket(9090);
    
            //固定线程池来接收处理
            Executor executor = Executors.newFixedThreadPool(3);
    
            //死循环,保证主线程不退出
            while (true){
                executor.execute(new SocketHandler(serverSocket.accept()));
            }
        }

    client客户端:

    public class Client {
    
        public void send(String message){
            Socket socket = null;
            BufferedReader bufferedReader = null;
            PrintWriter writer = null;
            try {
                socket = new Socket("127.0.0.1",9090);
    
                //发送数据到服务端
                writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
                writer.println(message);
                System.out.println("发送内容:	"+message);
    
                //接收服务端返回数据流
                bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String input = null;
                while ((input = bufferedReader.readLine()) != null){
                    System.out.println("接收服务端数据:	"+input);
                    //退出指令,关闭连接
                    writer.println("exit");
                    break;
                }
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (writer != null) writer.close();
                    if (bufferedReader != null) bufferedReader.close();
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) {
            Client client = new Client();
            for (int i = 0; i < 10; i++) {
                String text = RandomStringUtils.randomAlphabetic(5);
                client.send(text);
            }
        }

    PrintWriter 与 BufferedWriter 的区别:

      PrintWriter:是一种格式化对象的输出流,是一种高级流。此类实现了所有的PrintStream的print方法,它不包含用于写原始字节的方法,而对于原始字节,程序应该使用未编码的字节流。

    与PrintStream相比较,它具有自动行刷新的缓冲字符输出流。只需要在构造函数中指定参数autoFlush=true,使用方法println()即可实现自动行刷新。(println(xx) = print(xx) + println())。

    这个类中的方法永远不会抛出I/O异常,尽管它的一些构造函数可能抛出I/O异常。客户端可以通过调用checkError()来查询是否发生了错误。

    PrintWriter还可以直接与文件通信:

    new PrintWriter("c://text.txt");

      BufferedWriter:字符缓冲输出流(高级流),将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。 可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。

    提供了一个newLine()方法,通知流结束。因此如果把上面的PrintWriter 换成BufferedWriter

    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    bufferedWriter.write(result);
    bufferedWriter.newLine();
    bufferedWriter.flush();

     

  • 相关阅读:
    页面表单里的图片上传ENCTYPE="multipart/form-data"
    OSGI
    httpClient使用中报错org.apache.commons.httpclient.HttpMethodBase
    DNSPod--国内最早提供免费智能DNS产品的网站,致力于为各类网站提供高质量的多线智能DNS免费解析
    spring security 一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架
    Unable to parse request org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. null
    swfupload 上传报 security error # 2049 (security) 安全错误问题
    如何强制指定输入的参数必须为数字
    弹性盒子模型子元素垂直和水平居中
    Git常见错误处理
  • 原文地址:https://www.cnblogs.com/song27/p/14808903.html
Copyright © 2020-2023  润新知