java_进阶:网络编程

1、计算机网络

网络 是指将地理位置不同的具有地理功能的计算机及其外部设备 通过通信线路链接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

​ 网络编程 在网络通信协议下,实现网络互联的不同的计算机上运行的程序间可以进行数据交换

2、网络编程的三要素

  • IP地址 :网络中每一台计算机得唯一的标识号

  • ​端口:端口就是通过唯一标识锁定的设备上的应用程序的标识。

  • 协议:对数据的传输格式 传输速率 传输的步骤等做的统一的规定,将这种规则称为通信协议,双方都必须要遵守的,才能完成数据的交换。 常见的通信协议: UDP和 TCP

3、IP地址 – InetAddress

在 Java 中,使用 java.net 包下的 InetAddress 类表示互联网协议的 IP 地址。

下面列出了通过 InetAddress 类的静态方法获取 InetAddress 对象的方法。

InetAddress[]getAllByName(String host):在给定主机名的情况下,根据系统上配置的名称服务 host 返回其 IP 地址所组成的数组。
InetAddressgetByAddress(byte[] addr):给定字节数组形式的 IP 地址,返回 InetAddress 对象。
InetAddressgetByAddress(String host, byte[] addr):根据提供的主机名 host 和字节数组形式的 IP 地址 addr,创建 InetAddress 对象。
InetAddressgetByName(String host):给定主机名 host,返回 InetAddress 对象。
InetAddressgetLocalHost():返回本地主机 InetAddress 对象。

InetAddress 类的其他常用方法有以下几种:

byte[]getAddress():返回此 InetAddress 对象的原始 IP 地址。
StringgetCanonicalHostName():返回此 IP 地址的完全限定域名。完全限定域名是指主机名加上全路径,全路径中列出了序列中所有域成员。
StringgetHostAddress():返回 IP 地址字符串。
StringgetHostName():返回此 IP 地址的主机名。
    public static void main(String[] args) throws UnknownHostException {
        // 所有与网络编程先关的类 都位于java.net包下
        InetAddress address = InetAddress.getLocalHost();
        System.out.println(address.getHostName());//DESKTOP-RK7RI6L
        InetAddress  address1 = InetAddress.getByName("10.96.106.111");
        System.out.println(address1.getHostAddress());// 获取IP地址字符串
    }

4、端口

是程序在设备上的标识号

端口号:是用两个字节表示的整数,他的取值范围 0—65535 其中 0–1023之间的端口号主要用于一些网络服务和应用。在自己编写网络程序的时候 尽量使用1024以上的端口

5、 协议

  • UDP协议: 用户数据报协议

UDP协议是无连接的通信协议,在数据传输时,数据的发送端和接收端不建立逻辑链接。

优点:UDP协议消耗资源少,通信的效率高。

  • TCP:传输控制协议

TCP协议是面向链接的通信协议,在数据传输之前,必须在发送端和接收端之间建立逻辑链接,然后才能传输数据。可以提供两台设备之间的可靠无差错通信。

TCP协议区分发送端和接收端。

TCP协议的链接的建立:

​ TCP协议的链接需要经过“三次握手”
​ TCP协议断开链接是 需要经过“四次挥手”

6、 UDP协议通信程序

UDP是属于一种不可靠的协议 ,在通信的两端 需要建一个Socket(网络套接字)对象。但是这两个Socket只是发送和接收数据的对象,因此对于基于UDP协议的通信而言,没有所谓的客户端和服务器的概念。

DataGramSocket 基于UDP协议的Socket

  • 此类表示用于发送和接收数据报数据包的套接字。
  • 数据报套接字是分组传送服务的发送或接收点。

构造方法:

DatagramSocket() 构造数据报套接字并将其绑定到本地主机上的任何可用端口。
protectedDatagramSocket(DatagramSocketImpl impl) 使用指定的DatagramSocketImpl创建一个未绑定的数据报套接字。
DatagramSocket(int port) 构造数据报套接字并将其绑定到本地主机上的指定端口。
DatagramSocket(int port, InetAddress laddr) 创建一个数据报套接字,绑定到指定的本地地址。
DatagramSocket(SocketAddress bindaddr) 创建一个数据报套接字,绑定到指定的本地套接字地址。
voidreceive(DatagramPacket p) 从此套接字接收数据报包。
voidsend(DatagramPacket p) 从此套接字发送数据报包。

DatagramPacket:

  • 该类表示数据报包。数据报包用于实现无连接分组传送服务。
DatagramPacket(byte[] buf, int length) 构造一个 DatagramPacket用于接收长度的数据包 length
DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。
DatagramPacket(byte[] buf, int offset, int length) 构造一个 DatagramPacket用于接收长度的分组 length ,指偏移到缓冲器中。
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) 构造用于发送长度的分组数据报包 length具有偏移 ioffset指定主机上到指定的端口号。
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) 构造用于发送长度的分组数据报包 length具有偏移 ioffset指定主机上到指定的端口号。
DatagramPacket(byte[] buf, int length, SocketAddress address) 构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。

发送数据的步骤:
​ 1 创建发送端的Socket对象 DataGramSocket
​ 2 创建数据 并将数据打包 DatagramPacket
​ 3 调用DataGramSocket 的send方法 发送数据
​ 4 关闭发送端 close

public class SendSocket {
    public static void main(String[] args) throws IOException {
//        1 创建发送端的Socket对象 DataGramSocket
        DatagramSocket  ds = new DatagramSocket();
//	2 创建数据  并将数据打包  DatagramPacket
        byte[] packet= "hello  UDP".getBytes(StandardCharsets.UTF_8);
        DatagramPacket dp = new DatagramPacket(packet,packet.length, InetAddress.getByName("127.0.0.1"),10086);
//	3 调用DataGramSocket 的send方法  发送数据
     ds.send(dp);
//	4 关闭发送端  close
        ds.close();
    }
}

接收数据步骤
1 创建接收端你的Socket对象:DataGramSocket
2 创建一个数据报包 用于接收数据DatagramPacket
3 调用DataGramSocket的reveive接收
4 解析数据报包,把信息输出
5 关闭接收端

public class SendSocket {
    public static void main(String[] args) throws IOException {
//        1 创建发送端的Socket对象 DataGramSocket
        DatagramSocket  ds = new DatagramSocket();
//	2 创建数据  并将数据打包  DatagramPacket
        byte[] packet= "hello  UDP".getBytes(StandardCharsets.UTF_8);
        DatagramPacket dp = new DatagramPacket(packet,packet.length, InetAddress.getByName("127.0.0.1"),10086);
//	3 调用DataGramSocket 的send方法  发送数据
     ds.send(dp);
//	4 关闭发送端  close
        ds.close();
    }
}

TCP

TCP是一个可靠的网络协议,在通信两端各建立一个socket 对象,在通信两端形成网络的虚拟链接 两端程序通过虚拟链接进行通信

1、客户端 socket

该类实现客户端套接字(也称为“套接字”)。 套接字是两台机器之间通讯的端点。

Socket() 创建一个未连接的套接字,并使用系统默认类型的SocketImpl。
| ` `  | `Socket(InetAddress address, int port)`  创建流套接字并将其连接到指定IP地址的指定端口号。 |
|   | `Socket(String host,  int port)`  创建流套接字并将其连接到指定主机上的指定端口号。
| `InputStream` | `getInputStream()`  返回此套接字的输入流。 
| `OutputStream` | `getOutputStream()`  返回此套接字的输出流。 |
// 客户端  发送数据  接受服务器的反馈
public class ClinetDemo1 {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",10000);
        //写数据
        OutputStream os = socket.getOutputStream();
        os.write("hello TCP  我来了!".getBytes(StandardCharsets.UTF_8));
        //接受服务端的反馈 读数据
        InputStream is = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = is.read(bytes);
        System.out.println("服务端的反馈信息:"+new String(bytes,0,len));
        //释放资源  关闭socket  同时也就关闭了  OutputStream 和 InputStream
        socket.close();
    }
}

2、服务端 serverSocket

这个类实现了服务器套接字。 服务器套接字等待通过网络进入的请求。 它根据该请求执行一些操作,然后可能将结果返回给请求者。

ServerSocket() 创建未绑定的服务器套接字。
ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
Socketaccept() 侦听要连接到此套接字并接受它。
voidclose() 关闭此套接字。
//	服务端 收到客户端的数据后要各处反馈信息
 public class ServerScoketDemo1 {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(10000);
        Socket socket = server.accept();
        //读数据
       InputStream is =  socket.getInputStream();
       byte[] bytes = new byte[1024];
       int len = is.read(bytes);
        System.out.println("客户端发送的数据为:" +new String(bytes,0,len));
        //给出客户端反馈
       OutputStream os =  socket.getOutputStream();
       os.write("欢迎你的到来".getBytes(StandardCharsets.UTF_8));
       socket.close();
       server.close();
    }
}

3、 升级改造

需求:

客户端: 数据来自于键盘 直到录入bye,发送数据结束

服务端 接受到客户端的数据 并给出反馈

public class ClientDemo2 {
    public static void main(String[] args) throws IOException {
        Socket client = new Socket("127.0.0.1",9999);
        //数据来源于键盘
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 写出数据
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
        //数据来源于键盘
        BufferedReader br1 = new BufferedReader(new InputStreamReader(client.getInputStream()));
        // 写出数据
        BufferedWriter bw1 = new BufferedWriter(new OutputStreamWriter(System.out));

        String line;
        while((line=br.readLine())!=null) {
            if ("bye".equals(line)) {
                break;
            }
            bw.write(line);
            bw.newLine();
            bw.flush();
           String line1 =  br1.readLine();
           bw1.write(line1);
           bw1.newLine();
           bw1.flush();
        }
        client.close();
    }
}

public class ServerSocketDemo2 {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(9999);
        Socket socket = server.accept();
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw1 = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        String line;
        while((line=br.readLine())!=null){
            bw.write(line);
            bw.newLine();
            bw.flush();
            String line1 =   br1.readLine();
            bw1.write(line1);
            bw1.newLine();
            bw1.flush();
        }
    }
}

4 使用多线程来改造

一个线程充当客户端 另一个线程充当服务端

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值