Java之网络

目的

了解并学习网络,达到能在程序中运用网络的目的

知识点
  • 网络编程:在两台不同的计算机之间数据传递
  • 客户端:与服务器端相对的,为客户提供本地服务的程序,如:手机APP 浏览器 桌面QQ
  • 服务器端:存储/处理数据
  • URL:统一的资源定位
  • 网址表示:当我们打开浏览器随便输入什么,比如:输入android时
    它的网址是https://www.so.com/s?q=android&src=srp&fr=360_wsyjsw_recom3.7.1&ls=sn2321298&lm_extend=ctype%3A4&psid=da1039746140ba0878ed253ad4300c1a
    他们分别代表:
    • http/https:传输协议 TCP/IP协议
    • www.baidu.com:域名 表示一台网络中的电脑
      ipv4 ipv6地址:唯一表示一台网络中的计算机
      32位:四个部分 每个部分是8个字节
      某台电脑的地址172.20.10.15<->www.baidu.com等价
      DNS服务器:域名解析
      将www.baidu.com类型的地址解析为对应的ip地址
  • search对应的后台程序文件php java jsp
  • ?表示运行这个程序需要的参数
  • code=android code是服务器端规定的字段
  • &如果有多个参数使用&符号链接
  • ip地址:表示某一台电脑
  • 端口号:用来标识这台电脑上的某一个进程 (80端口)
  • 数据传输:TCP/IP协议
  • TCP:面向连接的(安全的) 比如:打电话
  • UDP:面向无连接的(不安全的,但快) 比如:飞鸽传书
  • 网络中的数据传输:Socket实现->套接字
  • Socket:客户端
  • ServerSocket:服务器端
Java之网络_第1张图片
QQ图片20190822183404.jpg
内容

1.简单实现数据发送
2.手动输入内容发送
3.发送图片
4.实现对聊
5.实现群聊

具体内容
1.简单实现数据发送
     //模拟客户端
    class Client{
        public static void main(String[] args) throws IOException {
            //1.创建用于通信的socket
            //指明谁通信 ip地址 端口号
            Socket socket=new Socket("192.168.43.96",8915);
            //接收服务器端的数据
            BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
             //向服务器端发送数据
            String line= null;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
            //客户端向服务器端发送数据
            PrintStream ps=new PrintStream(socket.getOutputStream());
            ps.println("你好啊");
            socket.shutdownOutput();
         }
     }
    //模拟服务器端
    class Server{
    public static void main(String[] args) throws IOException {
    //1.创建服务器端的serversocket
    ServerSocket ss=new ServerSocket(8915);
    //2.获取连接的客户端的socket
    Socket clientSocket=ss.accept();
    //3.向客户端发送数据
    PrintStream ps=new PrintStream(clientSocket.getOutputStream());
    ps.println("登录成功");
    //输出完毕
    clientSocket.shutdownInput();
    //4.接收客户端发来的数据
    BufferedReader br=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    String line=null;
    while((line=br.readLine())!=null){
        System.out.println(line);
      }
   }
}

先运行服务器端再运行客户端

2.手动输入内容发送
  • 读取数据:服务器读取 客户端读取
    BufferedReader->InputStreamReader->socket.getInputStream()
    读取终端
    BufferedReader->InputStream->System.in
  • 输出:客户端输出 服务器输出
    BufferedWriter->OutputStream->socket.getOutputStream
    PrintStream->socket.Stream()
  • socket 扮演的是客户端
  • ServerSocket扮演的是服务器端

从服务器端输入,将输入的内容发送给客户端

客户端

  class MyClient {
  public static void main(String[] args) {
    //连接客户端的socket
    Socket socket=null;
    try{
        socket=new Socket("192.168.43.96",8662);
        //接收服务器端信息
        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line=null;
        while ((line=br.readLine())!=null){
            System.out.println(line);
        }

    }catch (IOException e){
        System.out.println("网络出错,请重新输入");
    }finally {
        try{
            socket.close();
         }catch (IOException e){
            e.printStackTrace();
         }
       }
    }
 }

服务器端

  class MyServer{
  public static void main(String[] args) {
    //创建ServerSocket
    try(ServerSocket ss=new ServerSocket(8662)) {
        //监听客户端的连接
        Socket socket=ss.accept();
        //从终端接收数据
        BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
        //获取向客户端输出数据的输出流
        PrintStream ps=new PrintStream(socket.getOutputStream());
        String line=null;
        while ((line=keyin.readLine()) !=null){
            //发送给客户端
            ps.println(line);
        }
        //发送给客户端
      } catch (IOException e) {
          e.printStackTrace();
       }
     }
  }
3.发送图片

实现客户端向服务器端发送图片

客户端

  class Client{
  public static void main(String[] args) throws IOException {
    //连接服务器端,获取socket
    Socket socket=new Socket("127.0.0.1",8089);
    //创建服务器端对应的输入流 用于接收服务器发来的数据
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    System.out.println(br.readLine());
    //向服务器端发送图片(文件)
    //1.将文件写入到内存
    String path="/Users/Administrator/Desktop/1564315747404.jpeg";
    FileInputStream fis=new FileInputStream(path);
    //2.创建字节流
    BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
    //3.将文件的内容一点一点的传输给服务器
    byte[] buf=new byte[1024];
    int len=-1;
    while ((len=fis.read(buf))!=-1){
        bos.write(buf,0,len);
    }
    socket.shutdownOutput();
    }
  }

服务器端

  class Server{
  public static void main(String[] args) throws IOException {
    //创建服务器端的ServerSocket
    ServerSocket ss=new ServerSocket(8089);
    //监听客户端连接
    //当有客户端来连接,服务器一直在这里等待
    //当有客户端连接这个服务器,就可以得到对应的server
    Socket socket=ss.accept();
    //创建客户端对应的输出流,用于向这个客户端发送数据
    PrintStream ps=new PrintStream(socket.getOutputStream());
    ps.println("连接成功,可以发送数据了");
    //接收客户端传递过来的图片
    BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
    //文件对应的输出流
    String path="/Users/Administrator/AndroidStudioProjects/javaday1/src/main/java/day12/Medica/1.jpeg";
    FileOutputStream fos=new FileOutputStream(path);
    byte[] buf=new byte[1024];
    int len=-1;
    while ((len=bis.read(buf))!=-1){
        fos.write(buf,0,len);
      }
   }
}
4.实现对聊

使用多线程实现对聊

  • 客户端和服务器端都可以随意的发送内容
  • 从终端输入
  • 客户端
    主线程:接收终端输入 将终端输入发送给服务器端
    子线程;接收服务器端发过来的内容
  • 服务器端
    主线程:接收终端输入 将终端输入发送给客户端
    子线程:接收客户端发过来的数据

客户端

  class Client{
  public static void main(String[] args) throws IOException {
    Socket socket=new Socket("127.0.0.1",8087);
    //主线程处理终端输入发送给服务器端
    BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
    PrintStream ps=new PrintStream(socket.getOutputStream());
    //用一个子线程处理服务器端的数据
    new Thread(new ClientThread(socket)).start();
    String line=null;
    while ((line=keyin.readLine())!=null){
        ps.println(line);
    }
  }
}
  • 创建一个子线程处理客户端接收服务器端的数据
  class ClientThread implements Runnable{
  private Socket socket;
  //保存操作的socket对象
  public ClientThread(Socket socket){
    this.socket=socket;
  }
  @Override
  public void run() {
    //获取服务器端的输入流对象
    BufferedReader br= null;
    try {
        br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line=null;
        while((line=br.readLine())!=null){
            System.out.println(line);
        }
    } catch (IOException e) {
        System.out.println("网络连接错误,请重新输入");
        e.printStackTrace();
    }finally {
        try {
            if (br != null) {
                br.close();
            }
            if (socket!=null){
                socket.close();
            }
        }catch (IOException e){

        }
      }
   }
}

服务器端

  class Server{
  public static void main(String[] args) throws IOException {
    ServerSocket ss=new ServerSocket(8087);
    //接收客户端的socket
    Socket socket=ss.accept();
    //创建子线程 处理客户端输入数据
    new ServerThread(socket).start();
    //终端输入流对象
    BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
    //客户端输出流
    PrintStream ps=new PrintStream(socket.getOutputStream());
    //读取终端输入,将输入输出给客户端
    String line=null;
    while ((line=keyin.readLine())!=null){
        ps.println(line);
     }
   }
}

创建一个子线程处理服务端接收客户端的数据

  class ServerThread extends   Thread{
  private Socket socket;
  public ServerThread(Socket socket){
    this.socket=socket;

  }

  @Override
  public void run() {
    BufferedReader br=null;
    try {
        br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line=null;
        while ((line=br.readLine())!=null){
            System.out.println(line);
        }
    } catch (IOException e) {
        System.out.println("网络异常,请重新登录");
        e.printStackTrace();
    } finally {
        //关闭输入输出流
        try {
            if (br!=null){
                br.close();
            }
            if (socket!=null){
                socket.close();
            }
        }catch (IOException e){

         }
      }
   }
}
5.实现群聊

客户端

  class Client{
  public static void main(String[] args) throws IOException {
    Socket socket=new Socket("127.0.0.1",5001);
    //主线程处理终端输入发送给服务器端
    BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
    PrintStream ps=new PrintStream(socket.getOutputStream());
    //用一个子线程处理服务器端的数据
    new Thread(new ClientThread(socket)).start();
    String line=null;
    while ((line=keyin.readLine())!=null){
        ps.println(line);
     }

  }
}
  class ClientThread implements Runnable{
  private Socket socket;
  //保存操作的socket对象
  public ClientThread(Socket socket){
      this.socket=socket;
  }
  @Override
  public void run() {
    //获取服务器端的输入流对象
    BufferedReader br= null;
    try {
        br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line=null;
        while((line=br.readLine())!=null){
            System.out.println(line);
        }
    } catch (IOException e) {
        System.out.println("网络连接错误,请重新输入");
        e.printStackTrace();
    }finally {
        try {
            if (br != null) {
                br.close();
            }
            if (socket!=null){
                socket.close();
            }
          }catch (IOException e){

          }
        }
     }
 }

服务器端

  class Server{
  //保存每一个连接过来的对象
  public static ArrayList sockets=new ArrayList<>();
  public static void main(String[] args) throws IOException {
      ServerSocket ss=new ServerSocket(5001);
    //不停的等待客户端来连接数据
    while (true) {
        Socket socket = ss.accept();
        //当有客户端过来了就保存
        sockets.add(socket);
        //开启一个线程处理客户端的输入
        new ServerThread(socket).start();
        }
     }
  }
  class ServerThread extends Thread{
  private Socket socket;
  public ServerThread(Socket socket){
      this.socket=socket;

  }

  @Override
  public void run() {
      BufferedReader br=null;
      try {
        br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line=null;
        while ((line=br.readLine())!=null){
            //群发消息
            //遍历Server维护的每一个数组
            for (Socket s:Server.sockets){
                //向socket对应的客户端发送消息
                PrintStream ps=new PrintStream(s.getOutputStream());
                ps.println(line);
            }
        }
    } catch (IOException e) {
        System.out.println("网络异常,请重新登录");
        e.printStackTrace();
    } finally {
        //关闭输入输出流
        try {
            if (br!=null){
                br.close();
            }
            if (socket!=null){
                socket.close();
            }
        }catch (IOException e){

         }
      }
   }
}
小结

慢慢地,我们正在将前面学过的知识运用到不同的场景,实现知识融合,这是很好的将短期记忆转化成长期记忆的方法,不仅仅学习了新知识,还将学过的一并实现。我们一起回想加深对其的理解。我相信,编程这条路虽难,但越难的东西越能激起人的挑战欲,让我进步,我会继续加油的。

你可能感兴趣的:(Java之网络)