网络通信

一、七层网络模型OSI

  • OSIOpen System Interconnect),从上到下包括应用层-表示层-会话层-传输层-网络层-数据链路层-物理层  
  • TCP/IP 模型:应用层-传输层-网络层-数据链路层-物理层

 

二、基于TCP的编程模型

  • 服务器
    • 创建ServerSocket类型的对象并提供端口号
    • 调用accept方法等待客户端连接请求
    • 使用输入输出流进行通信,getInputStream()和getOutputStream()
    • 关闭资源,释放Socket
  • 客户端
    • 创建Socket对象并提供连接的服务器地址和端口号
    • 使用输入输出流进行通信
    • 关闭资源释放Socket
  • 常用类
    • java.net.ServerSocket类主要用于描述服务器套接字信息(大插排)。
      方法声明 功能介绍
      ServerSocket(int port) 根据参数指定的端口号来构造对象
      Socket accept() 侦听并接收到此套接字的连接请求
      void close() 用于关闭套接字
    • java.net.Socket类主要用于描述客户端套接字,是两台机器间通信的端点(小插排)。
      方法声明 功能介绍
      Socket(String host, int port) 根据指定主机名和端口来构造对象
      InputStream getInputStream() 用于获取当前套接字的输入流
      OutputStream getOutputStream() 用于获取当前套接字的输出流
      void close() 用于关闭套接字
package com.rf;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class ClientInput extends Thread {
    private Socket socket;
    private PrintStream ps = null;

    public ClientInput(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        Scanner sc = new Scanner(System.in);
        String s = null;
        while (true) {
            try {
                //(2)使用输入输出流进行通信;
                s = sc.nextLine();
                ps = new PrintStream(socket.getOutputStream(), true);
                ps.println(s);
                if (s.contains("bye")) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }
}
package com.rf;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class ClientOutput extends Thread {
    private Socket socket;
    private BufferedReader br = null;

    public ClientOutput(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        String s = null;
        try {
            while (true) {
                br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                s = br.readLine();
                if(s!=null)
                {System.out.println(s);
                if(s.contains("bye")){
                    System.out.println("用户已下线");
                }
                }
                else break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package com.rf;


import java.io.IOException;
import java.net.Socket;

public class ClientTest1 {
    public static void main(String[] args) {
        try {
            Socket socket=new Socket("127.0.0.1",9999);
            new ClientInput(socket).start();
            new ClientOutput(socket).start();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
package com.rf;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
import java.util.List;


public class Server {
    public static List<Socket> sockets = new LinkedList<>();

    public static void main(String[] args) {
        ServerSocket ss = null;
        Socket socket = null;
        try {
            //(1)创建ServerSocket类型的对象并提供端口号;
            ss = new ServerSocket(9999);
            System.out.println("正在等待客户端的连接请求.....");
            while (true) {
                //(2)等待客户端的连接请求,调用accept()方法;
                socket = ss.accept();
                System.out.println("客户端" + socket.getInetAddress() + "已上线...");
                sockets.add(socket);
                new ServerTalk(sockets, socket).start();
            }
            //  (4)关闭Socket;
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

package com.rf;

import java.io.*;
import java.net.Socket;
import java.util.List;

public class ServerTalk extends Thread {
    private List<Socket> sockets;
    private Socket client;

    BufferedReader br = null;

    public ServerTalk(List<Socket> sockets, Socket client) {
        this.sockets = sockets;
        this.client = client;
        //(3)使用输入输出流进行通信;
        try {
            br = new BufferedReader(new InputStreamReader(client.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void run() {
        String str = null;
        try {
            while (true) {
                str = br.readLine();
                System.out.println(client.getPort() + ":" + str);
                for (Socket s : sockets) {
                    PrintStream ps = new PrintStream(s.getOutputStream(), true);
                    if (s != client) {
                        ps.println(s.getPort() + ":" + str);

                    } else if(s==client)
                       { if (str.contains("bye")) {
                        ps.close();}
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

三、基于UDP的编程模型

  • 接收方
    • 创建DatagramSocket对象并提供端口号
    • 创建DatagramPacket对象并提供缓冲区
    • 通过Socket接收数据内容并存放到Packet中,调用receive()方法
    • 关闭资源释放Socket
  • 发送方
    • 创建DatagramSocket对象
    • 创建DatagramPacket对象并提供接收方的通信地址
    • 通过Socket将Packet内容发送出去,调用send()方法
    • 关闭资源释放Socket
  • 常用类
    • java.net.DatagramSocket类主要用于描述发送和接收数据报的套接字
      方法声明 功能介绍
      DatagramSocket() 使用无参的方式构造对象
      DatagramSocket(int port) 根据参数指定的端口号来构造对象
      void receive(DatagramPacket p) 用于接收数据报存放到参数指定的位置
      void send(DatagramPacket p) 用于将参数指定的数据报发送出去
      void close() 关闭Socket并释放相关资源
    • java.net.DatagramPacket类主要用于描述数据报,数据报用来实现无连接包裹投递服务
      方法声明 功能介绍
      DatagramPacket(byte[] buf, int length) 根据参数指定的数组来构造对象,用于接
      收长度为length的数据报
      DatagramPacket(byte[] buf, int length,
      InetAddress address, int port)
      根据参数指定数组来构造对象,将数据报
      发送到指定地址和端口
      InetAddress getAddress() 用于获取发送方或接收方的通信地址
      int getPort() 用于获取发送方或接收方的端口号
      int getLength() 用于获取发送数据或接收数据的长度
    • java.net.InetAddress类主要用于描述互联网通信地址信息。
      方法声明 功能介绍
      static InetAddress getLocalHost() 用于获取当前主机的通信地址
      static InetAddress getByName(String host) 根据参数指定的主机名获取通信地址
        

      package com.udp;
      
      import java.net.DatagramPacket;
      import java.net.DatagramSocket;
      import java.net.InetAddress;
      import java.net.SocketException;
      import java.util.Arrays;
      
      public class Send {
          public static void main(String[] args) throws Exception {
              //    创建DatagramSocket对象
              DatagramSocket datagramSocket=new DatagramSocket(6886);
              //    创建DatagramPacket对象并提供接收方的通信地址
              byte[] bytes = new byte[1024];
              for(int i=0;i<100;i++){
                  bytes[i]=(byte) i;
              }
              DatagramPacket datagramPacket=new DatagramPacket(bytes,10, InetAddress.getLocalHost(),6666);
              //    通过Socket将Packet内容发送出去,调用send()方法
              datagramSocket.send(datagramPacket);
              datagramPacket=new DatagramPacket(bytes,10,10);
              datagramSocket.receive(datagramPacket);
              System.out.println(Arrays.toString(bytes));
              //    关闭资源释放Socket
              datagramSocket.close();
          }
      }
      package com.udp;
      
      import java.net.DatagramPacket;
      import java.net.DatagramSocket;
      import java.net.InetAddress;
      import java.net.Socket;
      import java.util.Arrays;
      
      public class Receive {
      
          public static void main(String[] args) {
              DatagramSocket datagramSocket = null;
              DatagramPacket datagramPacket=null;
              try {
                  //创建 DatagramSocket对象并提供端口号
                  datagramSocket=new DatagramSocket(6666);
                  //创建 datagramPacket提供缓冲区
                  byte[] b= new byte[1024];
                  datagramPacket=new DatagramPacket(b,100);
                 //DatagramSocket对象接收数据内容
                  datagramSocket.receive(datagramPacket);
                  System.out.println(Arrays.toString(b));
      
                  //回发数据
                  datagramPacket=new DatagramPacket(b,10, InetAddress.getLocalHost(),6886);
                  datagramSocket.send(datagramPacket);
      
              } catch (Exception e) {
                  e.printStackTrace();
              }finally {
                  datagramSocket.close();
              }
          }
      }

四、URL类

  • java.net.URLUniform Resource Identifier)类主要用于表示统一的资源定位器,也就是指向万维网上资源的指针。这个资源可以是简单的文件或目录,也可以是对复杂对象的引用,例如对数据库或搜索引擎的查询等
  • 格式:<传输协议>://<主机名>:<端口号>/<资源地址>
方法声明 功能介绍
URL(String spec) 根据参数指定的字符串信息构造对象
String getProtocol() 获取协议名称
String getHost() 获取主机名称
int getPort() 获取端口号
String getPath() 获取路径信息
String getFile() 获取文件名
URLConnection openConnection() 获取URLConnection类的实例

五、URLConnection

  • java.net.URLConnection类是个抽象类,该类表示应用程序和URL之间的通信链接的所有类的超类,主要实现类有支持HTTP特有功能的HttpURLConnection
方法声明 功能介绍
InputStream getInputStream() 获取输入流
void disconnect() 断开连接



package com.com;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class URLTest {
    public static void main(String[] args) throws Exception {
        URL url = new URL("https://kaiwu.lagou.com");
        System.out.println(url.getProtocol());//协议
        System.out.println(url.getHost());//主机
        System.out.println(url.getPath());//路径
        System.out.println(url.getFile());//文件
        System.out.println(url.getPort());//端口
        System.out.println("-----------------");
        URLConnection urlConnection =(HttpURLConnection) url.openConnection();
        InputStream inputStream = urlConnection.getInputStream();
        BufferedReader br=new BufferedReader(new InputStreamReader(inputStream));
        String str=null;
        while ((str=br.readLine())!=null){
            System.out.println(str);
        }
    }
}

 

 

 

posted @ 2021-03-17 20:56  forever_fate  阅读(119)  评论(0)    收藏  举报