Java学习--网络编程

Java学习第三阶段

网络相关概念

1. IP地址

image-20220412212207521

image-20220413092527743

2. 域名和端口

image-20220413092835312

image-20220413093728682

3. 网络通信协议

image-20220413093913943

image-20220413094742944

image-20220413094859316

4. TCP 和 UDP

image-20220413095610642

网络编程

1. InetAddress 类

package Network01;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddress01 {
    public static void main(String[] args) throws UnknownHostException {
        //1.获取本机的InetAddress对象 getLocalHost
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost);//DESKTOP-JT4ULL5/192.168.3.5

        //2.根据指定主机名,获取InetAddress对象
        InetAddress localHost2 = InetAddress.getByName("DESKTOP-JT4ULL5");
        System.out.println(localHost2);//DESKTOP-JT4ULL5/192.168.3.5

        //3.根据域名返回 InetAddress对象
        InetAddress netHost = InetAddress.getByName("www.baidu.com");
        System.out.println(netHost);//www.baidu.com/39.156.66.18

        //4.通过InetAddress对象获取地址
        //ip地址
        String ip = netHost.getHostAddress();
        System.out.println(ip);//39.156.66.18

        //5.通过InetAddress对象获取对应的主机名/域名
        String hostName = netHost.getHostName();
        System.out.println(hostName);//www.baidu.com

    }
}

image-20220413101934686

2. Socket

image-20220413102103912

image-20220413104413924

3. TCP网络通信编程

image-20220413104534966

image-20220413160642182

//状态是LISTENING    表示该端口在监听
//	    ESTABLISHED 表示有外部端口连接到该端口

image-20220413171934067

//而查看监听某端口的程序是哪个 
netstat -anb
netstat -anb|more

image-20220413172651537

我只执行了Socket实例中的Server端,从上面的图片发现 9999 端口是被java程序在监听

image-20220413174444930

服务端的某一确定端口正在监听,如果有客户端希望服务端提供相应服务则连接该确定的端口,而实际上客户端也会有个由TCP/IP分配的端口进行与服务端通信操作

应用实例1:

//          字节流
//1.编写一个服务端和一个客户端
//2.服务端在9999端口监听
//3.客户端连接到服务器端,发送“hello,server”然后退出
//4.服务器端接收到客户端发送的信息,输出,并退出



//Server.java
package Socket_;

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

public class Server {
    public static void main(String[] args) throws IOException {
        //1.在本机的 9999 端口监听,等待连接
        //细节:要求 9999 端口没有其他服务在监听
        //细节:这个ServerSocket 可以通过accept() 返回多个Socket(多个客户端连接服务器的并发)
        ServerSocket serverSocket = new ServerSocket(9999);

        //2.当没有客户端连接 9999 端口时,程序会阻塞,并继续监听,等待连接
        //  如果有客户端连接,则会返回Socket对象,程序继续
        System.out.println("Service port 9999 is waiting...");
        Socket socket = serverSocket.accept();
        //如果serverSocket没有收到连接,则不会执行下面的println
//        System.out.println("服务器端socket = "+socket.getClass());

        //3.通过socket对象 接收数据通道的数据
        InputStream inputStream = socket.getInputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) > 0) {
            System.out.println(new String(buffer,0,len));
        }
        //4.关闭流对象,和socket
        inputStream.close();
        socket.close();
    }
}


//Client.java
package Socket_;

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

public class Client {
    public static void main(String[] args) throws IOException {
        //1.连接服务端(ip,端口)
        // 连接本机的 9999 端口
        // 当然也可以连接非本机的ip 和 端口
        // 如果连接成功,返回socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端socket返回 = "+socket.getClass());
        //2.连接成功后,得到了socket对象,并通过socket对象相关输入输出流进行数据传输,传输到数据通道
        OutputStream outputStream = socket.getOutputStream();
        //3.通过输出流,写入数据到数据通道
        outputStream.write("hello, server".getBytes());
        //4.关闭流对象 和 socket,必须关闭,否则其他服务不能接入
        outputStream.close();
        socket.close();
    }
}

应用实例2,实例1的加强版

//          字节流
//1.编写一个服务端和一个客户端
//2.服务端在9999端口监听
//3.客户端连接到服务器端,发送“hello,server”
//4.服务器端接收到客户端发送的信息,输出该信息,并发送”hello,client”给客户端,并退出
//5.客户端接收服务端的信息并输出,然后退出

/*这里加了设置结束标记 shutdownOutput() --结束输出数据 */


//Server.java
package Socket_2;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        //1.在本机的 9999 端口监听,等待连接
        //细节:要求 9999 端口没有其他服务在监听
        //细节:这个ServerSocket 可以通过accept() 返回多个Socket(多个客户端连接服务器的并发)
        ServerSocket serverSocket = new ServerSocket(9999);

        //2.当没有客户端连接 9999 端口时,程序会阻塞,并继续监听,等待连接
        //  如果有客户端连接,则会返回Socket对象,程序继续
        System.out.println("Service port 9999 is waiting...");
        Socket socket = serverSocket.accept();
        //如果serverSocket没有收到连接,则不会执行下面的println
        System.out.println("服务器端socket = "+socket.getClass());

        //3.通过socket对象 接收数据通道的数据
        InputStream inputStream = socket.getInputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) > 0) {
            System.out.println(new String(buffer,0,len));
        }
        
        //4.通过socket对象 向数据通道发送数据
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello,client".getBytes());
        //设置结束标记,不然对方不知道你是否结束数据传输了
        socket.shutdownOutput();

        //5.关闭流对象,和socket
        socket.close();
        inputStream.close();
        outputStream.close();

    }
}


//Client.java
package Socket_2;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        //1.连接服务端(ip,端口)
        // 连接本机的 9999 端口
        // 当然也可以连接非本机的ip 和 端口
        // 如果连接成功,返回socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端socket返回 = "+socket.getClass());
        //2.连接成功后,得到了socket对象,并通过socket对象相关输入输出流进行数据传输,传输到数据通道
        OutputStream outputStream = socket.getOutputStream();
        //3.通过输出流,写入数据到数据通道
        outputStream.write("hello, server".getBytes());
        //设置结束标记,不然对方不知道你是否结束数据传输了
        socket.shutdownOutput();

        //4.获取socket关联的输入流,并读取数据,并显示
        InputStream inputStream = socket.getInputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer))>0){
            System.out.println(new String(buffer,0,len));
        }

        //5.关闭流对象 和 socket,必须关闭,否则其他服务不能接入
        socket.close();
        outputStream.close();
        inputStream.close();
    }
}

应用实例3:实例2的另外一中方式–字符流

//          字符流
//1.编写一个服务端和一个客户端
//2.服务端在9999端口监听
//3.客户端连接到服务器端,发送“hello,server”
//4.服务器端接收到客户端发送的信息,输出该信息,并发送”hello,client”给客户端,并退出
//5.客户端接收服务端的信息并输出,然后退出

/*这里加了设置结束标记 shutdownOutput() --结束输出数据 */
/*这里设置结束标记也可以是 newLine(), 但是接收方必须用readLine() 来读取数据 */
/*注意:这里 字符流 写完数据必须使用flush(),否则数据无法写入到数据通道
* 	   字节流 设置结束标记后即可,可以不用flush()
*/


package Socket_3;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        //1.在本机的 9999 端口监听,等待连接
        //细节:要求 9999 端口没有其他服务在监听
        //细节:这个ServerSocket 可以通过accept() 返回多个Socket(多个客户端连接服务器的并发)
        ServerSocket serverSocket = new ServerSocket(9999);

        //2.当没有客户端连接 9999 端口时,程序会阻塞,并继续监听,等待连接
        //  如果有客户端连接,则会返回Socket对象,程序继续
        System.out.println("Service port 9999 is waiting...");
        Socket socket = serverSocket.accept();
        //如果serverSocket没有收到连接,则不会执行下面的println
        System.out.println("服务器端socket = "+socket.getClass());

        //3.通过socket对象 获取socket的字节输入流,并转换为字符输入流
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //字节流是byte【】,字符流是char【】
        char[] buffer = new char[1024];
        int len;
        while ((len = br.read(buffer)) != -1) {
            System.out.println(new String(buffer,0,len));
        }

        //4.通过socket对象 向数据通道发送数据
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write("hello,client");
        //必须加这个 flush() 否则写不到数据通道里去
        bw.flush();
        //设置结束标记,不然对方不知道你是否结束数据传输了
        //也可以使用 osw.newLine()设置结束标记,但是对方读取时要使用readLine()才能读取成功
        socket.shutdownOutput();

        //5.关闭流对象,和socket
        socket.close();
        br.close();
        bw.close();

    }
}

应用实例4:文件操作+网络编程

//1.编写一个服务端和一个客户端
//2.服务端在9999端口监听
//3.客户端连接到服务端,发送一张图片 E:\\view.jpg
//4.服务端接收到客户端发送的图片,保存到src下,发送“收到图片”再退出
//5.客户端接收到服务端发送的“收到图片”,再退出

//Server.java
package HomeWork01;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(9999);
        System.out.println("Service port 9999 is waiting...");
        Socket socket = server.accept();

        System.out.println("connect successfully: " + socket.getClass());
        OutputStream os = socket.getOutputStream();

        FileInputStream fileInputStream = new FileInputStream("E:\\view.jpg");
        byte[] bytes = new byte[1024];
        int len;
        while ((len = fileInputStream.read(bytes)) != -1) {
            os.write(bytes, 0, len);
        }
        socket.shutdownOutput();
        os.flush();

        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        char[] buf = new char[1024];
        len = br.read(buf);
        String s = new String(buf, 0, len);
        if (s.equals("收到图片")) {
            System.out.println(s);
            br.close();
            fileInputStream.close();
            os.close();
            socket.close();
        }
    }
}


//Client.java
package HomeWork01;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);

        FileOutputStream fileOutputStream = new FileOutputStream("E:\\view2.jpg");

        InputStream inputStream = socket.getInputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer))!=-1){
            fileOutputStream.write(buffer, 0, len);
        }

        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("收到图片".getBytes());
        socket.shutdownOutput();

        fileOutputStream.close();
        outputStream.close();
        inputStream.close();
        socket.close();
    }
}

4. UDP网络通信编程

image-20220413181634922

image-20220413181540978

image-20220413182215813

// 编程步骤
// 1.创建 接收/ 发送端的 DatagramSocket(确认自己要处理的端口号)
// 2.发送方创建DatagramPacket 将数据打包,
//   打包方式,可根据DatagramPacket构造函数来进行
//    其中,创建DatagramPacket要指定发送到哪个主机(ip)的哪个端口
// 3.接收方创建接收DatagramPacket,收到数据后,拆包从而获取数据
// 4,关闭 DatagramSocket

应用实例:

/* 先发后收方 -- 先发送信息给对方,后接收信息并输出,再退出
 * 先手后发方 -- 先接收到信息并输出,后发送信息,再退出 */


//先发后收方
//Send.java
package UDP.UDP_1;

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

public class Send {
    public static void main(String[] args) throws IOException {
        //1.创建DatagramSocket,在 9998 端口接收数据
        //主要是发送端和接收端都在同一个机器上,所以选择了两个不同的端口号
        //如果不在同一个机器上,则可以选择相同端口号,因为它们的ip都不同
        DatagramSocket datagramSocket = new DatagramSocket(9998);

        //2.将要发送的数据装包 DatagramPacket
        //  并根据接收方的主机名确定接收方的ip地址 ,和 端口号
        //  封装的 DatagramPacket对象 :内容,内容长度,主机(IP),端口
        //  这里可以查看API文档 查看getByName()可以填主机名,也可以填ip地址
        byte[] data = "hello,明天吃火锅".getBytes();
        DatagramPacket datagramPacket =
                new DatagramPacket(data, data.length, InetAddress.getByName("192.168.3.5"),9999);

        //3.发送数据包
        datagramSocket.send(datagramPacket);

        byte[] buf = new byte[1024];
        DatagramPacket receiveInfo = new DatagramPacket(buf, buf.length);
        System.out.println("waiting for message...");
        datagramSocket.receive(receiveInfo);

        int length = receiveInfo.getLength();
        byte[] info = receiveInfo.getData();
        String receiveData = new String(info,0,length);
        System.out.println(receiveData);


        datagramSocket.close();
    }
}


//先收后发方
//Receive.java
package UDP.UDP_1;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Receive {
    public static void main(String[] args) throws IOException {
        //1.创建DatagramSocket
        //  这里明确了接收数据的端口号 9999
        DatagramSocket datagramSocket = new DatagramSocket(9999);

        //2.构建一个DatagramPacket 对象,准备接收数据
        //  注意:一个数据包最大64K
        byte[] buf = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);

        //3.通过接收方法,将通过网络传输的 DatagramPacket 对象填充到 datagramPacket
        //  如果没有数据包发送到 9999 端口,则会阻塞
        System.out.println("waiting for message...");
        datagramSocket.receive(datagramPacket);

        //4.可以把packet进行拆包,取出数据,并显示
        int length = datagramPacket.getLength();//实际接收到的字节长度
        byte[] data = datagramPacket.getData();//接收到的数据

        String info = new String(data,0,length);
        System.out.println(info);

        data = "好呀".getBytes();
        DatagramPacket sendPacket = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.3.5"), 9998);
        datagramSocket.send(sendPacket);


        datagramSocket.close();

    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值