2019-04-05

作者: DreamPath | 来源:发表于2019-04-06 01:28 被阅读2次

    网络编程进阶整理

    案例一:实现客户端与服务端的交互

    频繁的客户端与服务端的通信

    需求:

    • 1.客户端通过键盘录入发送数据到服务器端,
    • 2.服务器端将接收到的数据显示到屏幕上的同时,将这些数据转成大写发回给客户端。
    • 3.当客户端录入的是over时,该客户结束转换。

    服务端

    package socket2.socketss;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     *  不管是服务端还是客户端都需要刷新。
     *  readLine方法是读取一行,必须指定行终止符
     *
     *      1.当没有使用PrintWriter构造方法中的,true自动刷新时,只能使用flush
     *      2.由于readLine方法必须要读到行终止符时才返回该数据,
     *      3.因此需要用+"/r/n" 或者属性集对象的换行常数的属性集
     *      4.然而最高效的方法是使用Println方法打印一行。
     */
    public class Socket_Server {
        public static void main(String[] args) throws IOException {
    
    //        服务端:
            System.out.println("服务端运行......");
    //        思路:
    //        1.创建服务端SeverSocket 明确端口
            ServerSocket ss = new ServerSocket(10009);
            while (true) {
                //服务端接收对象
                Socket s = ss.accept();
    //        2.socket输入流,读取客户端发过来的数据
                BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
    
                //将转化成的大写字母数据返回给客户端   true自动刷新
    //        3.目的:socket输出流,将转成大写数据发给客户端
                PrintWriter pwOut = new PrintWriter(s.getOutputStream(), true);
                //外加功能
                String IP = s.getInetAddress().getHostAddress();
                System.out.println(IP + "------connected");
    //        4.频繁的读写操作
    //        5.关闭该客户端
                //创建ServerSocket对象,并明确对象
                String line;
                while ((line = bufIn.readLine()) != null) {
                    if (line.equals("over")) {
                        break;
                    }
                    String LIN = line.toUpperCase();
                    //println()方法指定行终止符打印一行
                    pwOut.println(LIN);
                    System.out.println(LIN);
                }
                s.close();
            }
        }
    }
    

    客户端

    package socket2.socketss;
    
    import java.io.*;
    import java.net.Socket;
    /**
     * 客户端
     * 步骤:
     * 1.创建socket,明确地址和端口
     * 2.源:键盘录入,获取需要转换的数据
     * 3.目的,网络,socket输出流,将录入的数据发送到服务器
     * 4.源2:socket socket读取流,读取服务器发回来的大写数据
     * 5.目的:客户端显示,将大写数据显示出来。
     * 6.频繁读写操作
     * 7.关闭资源
     */
    public class Socket_Client {
        public static void main(String[] args) throws IOException {
    //        客户端
            System.out.println("客户端运行......");
    //        步骤:
    //        1.创建socket,明确地址和端口
            Socket s=new Socket("192.168.1.3",10009);
    //        2.源:键盘录入,获取需要转换的数据
            BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
    //        3.目的,网络,socket输出流,将录入的数据发送到服务器
    /*      OutputStream outSo=s.getOutputStream();
            //由于都是字符数换流,高效
            BufferedWriter buOut =new BufferedWriter(new OutputStreamWriter(outSo));*/
            //为了更方便,我们这使用打印流
            PrintWriter pwOut=new PrintWriter(s.getOutputStream(),true);
    
    //        4.源2:socket socket读取流,读取服务器发回来的大写数据
            BufferedReader buIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
    //        5.目的:客户端显示,将大写数据显示出来。
    //        6.频繁读写操作
            String line;
            while ((line=bf.readLine())!=null){
                //将数据发送给服务端
                pwOut.println(line);
                if ("over".equals(line)) {
                    break;
                }
                //将服务端返回的数据读取出来,并打印。
                String s1 = buIn.readLine();
                System.out.println(s1);
            }
    //        7.关闭资源
            s.close();
    
        }
    }
    

    案例三:
    文件上传
    服务端

    package socket;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class SeverSocket_File {
        public static void main(String[] args) throws IOException {
            //        服务端:
            System.out.println("服务端运行......");
    //        思路:
    //        1.创建服务端SeverSocket 明确端口
            ServerSocket ss = new ServerSocket(10010);
            System.out.println(ss.getInetAddress().getHostAddress() + "------------connected");
            //服务端持续操作
            while (true) {
                //服务端接收对象
                Socket s = ss.accept();
    //        2.socket输入流,读取客户端发过来的数据
                BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
    
                //        3.目的:socket输出流,将上传成功的数据
                PrintWriter pw = new PrintWriter(new FileWriter("D:\\Java代码\\Java基础加强\\Day12_socket\\src\\s.txt"), true);
    
    //        4.频繁的读写操作
                String line;
                while ((line = bufIn.readLine()) != null) {
    //                 if (line.equals("over")) {
    //                break;
    //            }
                    pw.println(line);
                }
                //服务端反馈数据给客户端
                PrintWriter out = new PrintWriter(s.getOutputStream(), true);
                out.println("文本上传成功");
                pw.close();
                s.close();
            }
        }
    }
    

    客户端

    package socket;
    
    import java.io.*;
    import java.net.Socket;
    
    /**
     * 文件上传
     * 原理:
     *      1.客户端读取文件,将数据发送给服务端 ,发送完毕标记
     *      2.服务端接收并读取客户端发来的数据,
     *      3.反馈 上传成功  的数据给客户端
     *      4.客户端接收并读取服务端成功信息,在这之前必须设定结束标记
     */
    public class Client_file {
        public static void main(String[] args) throws IOException {
    
            //        客户端
            System.out.println("客户端运行......");
    //        步骤:
    //        1.创建socket,明确地址和端口
            Socket s = new Socket("192.168.1.3", 10010);
    //        2.源:键盘录入,获取需要转换的数据
            BufferedReader bf = new BufferedReader(new FileReader("D:\\Java代码\\Java基础加强\\笔记.txt"));
    //        3.目的,网络,socket输出流,将文本中的数据发送到服务器
            PrintWriter pwOut = new PrintWriter(s.getOutputStream(), true);
    //        4.频繁读写操作
            String line;
            while ((line = bf.readLine()) != null) {
                //将数据发送给服务端
                pwOut.println(line);
            }
            //为了上传成功后,客户端能正常关闭,我们需要定义一个结束标记
            //   pwOut.println("over");
            //为了使得程序更吊一点,我们使用socket中的shutdownOutput().
            s.shutdownOutput();
    
            //   5.源2:socket socket读取流.读取服务端发回来的上传成功信息
            BufferedReader buIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
    
            String info = buIn.readLine();
    
            System.out.println(info);
    
    //        7.关闭资源
            s.close();
            bf.close();
    
        }
    }
    

    媒体文件的上传:
    为什么不能使用字符流来上传或者复制媒体文件
    原因:
    编码表中的数据不能完全包含字节二进制数据
    导致一种情况就是:无法解析某些字而出现乱码。
    图片上传服务端

    package socket3_pic;
    
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class SeverSocketDemo {
        public static void main(String[] args) throws IOException {
            System.out.println("服务端运行......");
            //创建ServerSocket对象
            ServerSocket ss = new ServerSocket(10011);
    
    //        创建socket对象
            while (true) {
                Socket s = ss.accept();
    
                String ip = s.getInetAddress().getHostAddress();
                System.out.println(ip+"--------connected");
                //源: 客户端获取的流
                InputStream sin = s.getInputStream();
    
                //目的:写入文件当中,需要使用文件File(非流类)类
                File f=new File("D:\\Java代码\\Java基础加强\\Day12_socket\\src\\socket");
                if (!f.exists()) {
                    f.mkdir();
                }
                int conut=1;
                //为了使得上传的文件不冲突,使用ip和遍历文件夹是否存在,计数器来限制文件名
                File file=new File(f,ip+"("+conut+")"+".jpg");
                while (file.exists()){
                    conut++;
                    file=new File(f,ip+"("+conut+")"+".jpg");
                }
                FileOutputStream out = new FileOutputStream(file);
                //频繁读写操作
                int len;
                byte[] bytes = new byte[1024 * 1024];
                while ((len = sin.read(bytes)) != -1) {
                    //将缓冲区中的数据全部写入到文件当中
                    out.write(bytes, 0, len);
                }
    
                //如果图片上传成功后,发送提示给客户端
                OutputStream sOut = s.getOutputStream();
                sOut.write("图片上传完毕".getBytes());
    
                s.close();
                out.close();
            }
        }
    
    }
    

    客户端

    package socket3_pic;
    
    import java.io.*;
    import java.net.Socket;
    
    
    public class UploadPicClient {
        public static void main(String[] args) throws IOException {
            System.out.println("客户端运行.......");
            //创建socket
            Socket s = new Socket("192.168.1.3", 10011);
    
            //获取字节数据源
            FileInputStream fin = new FileInputStream(new File("D:\\Java代码\\Java基础加强\\Day12_socket\\1.jpg"));
    
            //目的源:socket
            OutputStream out = s.getOutputStream();
    
            //频繁读写
            int len = 0;
            byte[] bytes = new byte[1024 * 1024];
    
            while ((len = fin.read(bytes)) != -1) {
                out.write(bytes, 0, len);
            }
            //结束标记,告诉服务端图片数据发送完毕,不要再继续读取了
            s.shutdownOutput();
    
            //读取服务端返回的图片上传状态
            InputStream sin = s.getInputStream();
    
            byte[] bytes1 = new byte[1024];
            int read = sin.read(bytes1);
            System.out.println(new String(bytes1, 0, read));
    
            //关闭资源
            fin.close();
            s.close();
    
        }
    }
    
    • 服务端使用多线程来获取客户端上传操作
    • 客户端保持不变
      服务端优化
    package socket2;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class SeverSocketDemo2 {
        public static void main(String [] args) throws IOException {
          System.out.println("服务端运行......");
        //创建ServerSocket对象
        ServerSocket ss = new ServerSocket(10011);
    
    //        创建socket对象
            while (true) {
                Socket s = ss.accept();
    
                //为了实现多个客户端并发访问,服务器必须启动多个线程来完成
                //然而对于阿里和新浪这些服务器是使用服务器集群来完成,更加需要硬件技术,跟软件技术相结合。
                new Thread(new UploadPic(s)).start();
    
            }
        }
    }
    

    上传图片的线程类

    package socket2;
    
    import java.io.*;
    import java.net.Socket;
    
    public class UploadPic implements Runnable {
        private Socket s;
        public UploadPic(Socket s) {
            this.s=s;
        }
    
        @Override
        public void run() {
           try {
               String ip = s.getInetAddress().getHostAddress();
               System.out.println(ip + "--------connected");
               //源: 客户端获取的流
               InputStream sin = s.getInputStream();
    
               //目的:写入文件当中,需要使用文件File(非流类)类
               File f = new File("D:\\Java代码\\Java基础加强\\Day12_socket\\src\\socket");
               if (!f.exists()) {
                   f.mkdir();
               }
               int conut = 1;
               //为了使得上传的文件不冲突,使用ip和遍历文件夹是否存在,计数器来限制文件名
               File file = new File(f, ip + "(" + conut + ")" + ".jpg");
               while (file.exists()) {
                   conut++;
                   file = new File(f, ip + "(" + conut + ")" + ".jpg");
               }
               FileOutputStream out = new FileOutputStream(file);
               //频繁读写操作
               int len;
               byte[] bytes = new byte[1024 * 1024];
               while ((len = sin.read(bytes)) != -1) {
                   //将缓冲区中的数据全部写入到文件当中
                   out.write(bytes, 0, len);
               }
    
               //如果图片上传成功后,发送提示给客户端
               OutputStream sOut = s.getOutputStream();
               sOut.write("图片上传完毕".getBytes());
    
               s.close();
               out.close();
           }catch (IOException e){
               e.printStackTrace();
           }
    
        }
    }
    

    相关文章

      网友评论

        本文标题:2019-04-05

        本文链接:https://www.haomeiwen.com/subject/fdjliqtx.html