网络编程

网络编程

InetAddress的使用

实例化方法:

  • InetAddressget ByName(String host) 使用IP地址或域名作为形参,生成一个IP地址的对象
  • InetAddressget LocalHost() 获取本机IP地址生成一个IP地址的对象

此类使用两个静态实例化方法,其对象就是一个IP地址,

常用方法:

  • getAddress() 返回IP地址
  • getHostAddress 返回域名

TCP和UDP

TCP
  • TCP的进程:客户端、服务端
  • 先建立链接才能使用
  • 三次握手,点对点通信,是可靠的
  • 连接时有大量数据传输
  • 传输完毕,需释放已经建立的链接,效率低
UDP
  • UDP的进程:发送端、接收端
  • 将数据封装成包,不需要建立链接
  • 不保证数据的完整性,是不可靠的
  • 一个数据包的大小限制到64K内
  • 发送数据结束时,无需释放资源,开销小,通信效率高

TCP案例

客户端发送数据,服务端保存数据

客户端服务端
1.创建Socket 指明对方的服务器端的IP地址和端口号1.创建Server Socket
2.创建File的实例、FileInputStream的实例2.接收来自于客户端的socket:accept() 二次握手
  1. 通过Socket,获取输出流 读写数据|3.通过socket获取一个输入流
    4.关闭相关流|4.创建File类的实例、FileOutStream的实例
    |5.关闭相关流
import org.junit.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
//注意:因为涉及到相关资源的关闭,所以需要使用try、catch、finally处理异常

public class TCPTest2 {
    @Test
    public void client() throws IOException {
        //1.创建Socket
        //指明对方的服务器端的IP地址和端口号
        InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
        int port = 9091;
        Socket socket = new Socket(inetAddress, port);
        //2.创建File的实例、FileInputStream的实例
        FileInputStream fis = new FileInputStream(new File("pic.jpg"));
        //3. 通过Socket,获取输出流
        OutputStream os = socket.getOutputStream();
        // 读写数据
        byte[] bytes = new byte[1024];
        int len;
        while ((len = fis.read(bytes)) != -1) {
            os.write(bytes, 0, len);
        }
        System.out.println("数据发送完毕");

        //客户端表明不再继续发送数据,如果不表明,服务端将不知道发没法完,只有shutdown和close才能表明发送完成
        socket.shutdownOutput();

        //接收来自于服务器端的数据
        InputStream is = socket.getInputStream();
        byte[] bytes1 = new byte[1024];
        int len1;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        while ((len1 = is.read(bytes1)) != -1) {
            baos.write(bytes1,0,len1);
        }
        System.out.println(baos);
        //4.关闭Socket相关的流
        is.close();
        baos.close();
        os.close();
        fis.close();
        socket.close();
    }


    @Test
    public void server() throws IOException {
        //1.创建Server Socket
        int port = 9091;
        ServerSocket serverSocket = new ServerSocket(port);
        //2.接收来自于客户端的socket:accept() 二次握手
        Socket socket = serverSocket.accept();
        //3.通过socket获取一个输入流
        InputStream is = socket.getInputStream();
        //4.创建File类的实例、FileOutStream的实例
        FileOutputStream fos = new FileOutputStream(new File("pic_copy.jpg"));
        //读写过程
        byte[] bytes = new byte[1024];
        int len;
        while ((len = is.read(bytes)) != -1) {
            fos.write(bytes, 0, len);
        }
        System.out.println("数据接收完毕");

        //发送数据回客户端,表示文件收到
        OutputStream os = socket.getOutputStream();
        os.write("你的图片很漂亮,我接受到了".getBytes(StandardCharsets.UTF_8));
        //5.关闭相关流
        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}



注:在多次反复传输数据时,客户端需使用shutdown和close表明不再继续发送数据,如果不表明,服务端将一直等待客户端发送,形成死锁


UDP案例
import org.junit.Test;


import java.io.IOException;
import java.net.*;

public class UDPTest {

    @Test
    public void sender() throws Exception {
        //创建DatagramSocket实例(此Socket为UDP传输对象)
        DatagramSocket ds = new DatagramSocket();
        //编辑一个包,作为socket发送的参数
        InetAddress byName = InetAddress.getByName("127.0.0.1");//ip
        int port = 9090;//端口号
        byte[] bytes = "我是发送端".getBytes("utf-8");//发送的内容(字符数组)
        DatagramPacket dp = new DatagramPacket(bytes, 0, bytes.length, byName, port);
        //发送数据
        ds.send(dp);
        ds.close();
    }

    @Test
    public void receiver() throws IOException {
        int port = 9090;
        //创建DatagramSocket实例
        DatagramSocket ds = new DatagramSocket(port);
        //创建数据包对象,用来接收包
        byte[] bytes = new byte[1024 * 64];
        DatagramPacket dp = new DatagramPacket(bytes, 0, bytes.length);
        //接收数据
        ds.receive(dp);
        //读取数据并打印到控制台上
        java.lang.String str = new java.lang.String(dp.getData(), 0, dp.getLength());
        System.out.println(str);
        ds.close();
    }
}


URL编程

URL(Uniform Resource Locator): 统一资源定位符

方法名说明
public String getProtocol()获取该URL的协议名
public String getHost()获取该URL的主机名
public String getPort()获取该URL的端口号
public String getPath()获取该URL的文件路径
public String getQuery()获取该URL的查询名
URL编程案例
import org.junit.Test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class URLTest1 {
    @Test
    public void test1(){
        HttpURLConnection urlConnection = null;
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            //1. 获取URL实例
            URL url = new URL("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png");
            //2. 建立http协议url链接
            urlConnection = (HttpURLConnection) url.openConnection();
            //3. 从连接中获取输入流读数据
            is = urlConnection.getInputStream();
            File file = new File("dest.jpg");
            //4. 将读到的数据写入本地
            fos = new FileOutputStream(file);

            byte[] bytes = new byte[1024];
            int len;
            while ((len = is.read(bytes)) != -1) {
                fos.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //5. 关闭资源
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            urlConnection.disconnect();//关闭url
        }
    }
}