Java之网络编程

一、什么是网络编程

在网络通信协议下,不同计算机上运行的程序,可以进行数据传输

二、常见的网络架构

1、B/S :Browser/Server

只需要一个浏览器,用户通过不同的网址,客户访问不同的服务器。

例如:京东,淘宝

2、C/S :Client/Server

在用户本地需要下载并安装客户端程序,在远程有一个服务器程序。

例如:QQ

3、优缺点 

  • B/S
    • 不需要开发客户端,只需要页面+服务器
    • 用户不需要下载,打开浏览器就能使用
    • 如果应用过大,用户体验受到影响
  • C/S
    • 画面可以做的非常精美,用户体验好
    • 需要开发客户端,也需要开发服务器
    • 用户需要下载和更新的时候太麻烦

三、网络编程三要素

(一)、IP地址

全称:Iinternet Protocol,是互联网协议地址,也称IP地址。是分配给上网设备的数字标签

IP是设备在网络中的地址,是唯一标识

1、IPv4

是给每个连接在网络上的主机分配一个32bit地址。按照TCP/IP规定,IP地址用二进制来表示,每个IP地址长32bit,也就是4个字节。例如一个采用二进制形式的IP地址是“11000000 10101000 00000001 01000010”,这么长的地址,处理起来也太费劲了。为了方便使用,IP地址经常被写成十进制的形式,中间使用符号“.”分隔不同的字节。于是,上面的IP地址可以表示为“192.168.1.66”。IP地址的这种表示法叫做“点分十进制表示法”,这显然比1和0容易记忆得多

2、IPv6 

由于互联网的蓬勃发展,IP地址的需求量愈来愈大,但是网络地址资源有限,使得IP的分配越发紧张。为了扩大地址空间,通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,这样就解决了网络地址资源数量不够的问题

3、InetAddress类

 此类表示互联网(IP)地址

  • 相关方法
static InetAddress getByName(String host)确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址
String getHostName()   获取此IP地址的主机名
String getHostAddress()返回文本显示中的IP地址字符串
public class Demo {
    public static void main(String[] args) throws UnknownHostException {
        // 获取InetAddress的对象,属性可以是ip地址,也可以是机器名称
        // InetAddress address= InetAddress.getByName("192.168.16.100");
        InetAddress address= InetAddress.getByName("DESKTOP-LED4SES");
        System.out.println(address);

        // 获取此IP地址的主机名
        String hostName = address.getHostName();
        System.out.println(hostName);

        // 返回文本显示中的IP地址字符串
        String ip = address.getHostAddress();
        System.out.println(ip);
    }
}

(二)、端口

应用程序在设备中唯一的标识

用两个字节表示的整数,它的取值范围是0~65535。其中,0~1023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。

(三)、协议

数据在网络中传输的规则,常见的协议有UDP、TCP、http、https、ftp。

  • OSI参考模型:世界互联协议标准,全球通信规范,单模型过于理想化,未能在因特网上进行广泛推荐
  • TCP/IP参考模型(TCP/IP协议):事实上的国际标准
1、UDP协议
  • 用户数据报协议(User Datagram Protocol)
  • UDP是面向无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
  • 由于使用UDP协议消耗系统资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输
  • 有大小限制,一次最多发送64KB,数据不安全,易丢失数据
2、TCP协议 
  • 传输控制协议 (Transmission Control Protocol)
  • TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手
  • 三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠
    • 第一次握手,客户端向服务器端发出连接请求,等待服务器确认
    • 第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求
    • 第三次握手,客户端再次向服务器端发送确认信息,确认连接
  • 完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛。例如上传文件、下载文件、浏览网页等

四、UDP通信程序 

UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象,因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念
Java提供了DatagramSocket类作为基于UDP协议的Socket

(一)、UDP发送数据

1、构造方法
  • DatagramSocket():创建数据报套接字并将其绑定到本机地址上的任何可用端口 |
  • DatagramPacket(byte[] buf,int len,InetAddress add,int port):创建数据包,发送长度为len的数据包到指定主机的指定端口 
2、相关方法
  • void send(DatagramPacket p):发送数据报包
  • void close():关闭数据报套接字
  • void receive(DatagramPacket p):从此套接字接受数据报包
3、发送数据的步骤
  1. 创建发送端的Socket对象(DatagramSocket)
  2. 创建数据,并把数据打包
  3. 调用DatagramSocket对象的方法发送数据
  4. 关闭发送端 
4、示例
public class SendMessageDemo {
    public static void main(String[] args) throws IOException {
        // 创建对象
        //    绑定对应端口
        //      空参:所有可用的端口中随机一个进行使用
        //      有参:指定端口号进行绑定
        DatagramSocket ds = new DatagramSocket();

        // 创建数据,并把数据打包
        byte[] bytes = "hello world".getBytes(StandardCharsets.UTF_8);
        InetAddress address = InetAddress.getByName("127.0.0.1");
        int port = 12345;

        DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
        
        // 发送数据
        ds.send(dp);

        // 释放资源
        ds.close();
    }
}

 (二)、UDP接收数据

1、接收数据的步骤
  1. 创建接收端的Socket对象(DatagramSocket)
  2. 创建一个数据包,用于接收数据
  3. 调用DatagramSocket对象的方法接收数据
  4. 解析数据包,并把数据在控制台显示
  5. 关闭接收端
2、示例
public class ReceiveMessageDemo {
    public static void main(String[] args) throws IOException {
        //创建接收端的Socket对象(DatagramSocket)
        //    在接受数据的时候,一定要绑定端口
        //    而且绑定的端口一定要跟发送的端口保持一致
        DatagramSocket ds = new DatagramSocket(12345);

        //创建一个数据包,用于接收数据
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);

        //调用DatagramSocket对象的方法接收数据
        //    该方法是阻塞的
        //    运行到这一步时,会等发送端发送消息
        ds.receive(dp);

        //解析数据包,并把数据在控制台显示
        byte[] data = dp.getData();
        int len = dp.getLength();
        InetAddress address = dp.getAddress();
        int port = dp.getPort();

        System.out.println("接收到的数据:" + new String(data, 0, len));
        System.out.println("address = " + address);
        System.out.println("port = " + port);

        //关闭接收端
        ds.close();
    }
}

注意:先启动接收端,再启动发送端

 五、UDP三种通讯方式

(一)、单播

单播用于两个主机之间的端对端通信

上面写的代码都是单播形式,不再演示

(二)、组播

组播用于对一组特定的主机进行通信

组播地址:224.0.0.0 ~ 239.255.255.255,其中224.0.0.0 ~ 224.0.0.255为预留的组播地址

1、实现步骤

发送端
    1. 创建发送端的Socket对象(DatagramSocket)
    2. 创建数据,并把数据打包(DatagramPacket)
    3. 调用DatagramSocket对象的方法发送数据(在单播中,这里是发给指定IP的电脑但是在组播当中,这里是发给组播地址)
    4. 释放资源


接收端
    1. 创建接收端Socket对象(MulticastSocket)
    2. 创建一个箱子,用于接收数据
    3. 把当前计算机绑定一个组播地址
    4. 将数据接收到箱子中
    5. 解析数据包,并打印数据
    6. 释放资源 

2、示例 
public class SendMessageDemo {
    public static void main(String[] args) throws IOException {
        // 1. 创建接收端Socket对象(MulticastSocket)
        MulticastSocket ms = new MulticastSocket();

        // 2. 创建DatagramPacket对象
        String str = "hello啊";
        byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
        InetAddress address = InetAddress.getByName("224.0.1.0");
        int port = 10000;

        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);

        // 3. 发送数据
        ms.send(dp);

        // 4. 释放资源
        ms.close();
    }
}
public class ReceiveMessageDemo1 {
    public static void main(String[] args) throws IOException {
        // 1. 创建发送端的Socket对象(DatagramSocket)
        MulticastSocket ms = new MulticastSocket(10000);

        // 2. 将当前本机,添加到224.0.0.1这一组中
        InetAddress address = InetAddress.getByName("224.0.1.0");
        ms.joinGroup(address);

        // 3. 创建数据包对象
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);

        // 4. 接收数据
        ms.receive(dp);

        // 5. 解析数据
        byte[] data = dp.getData();
        int len = dp.getLength();
        String ip = dp.getAddress().getHostAddress();
        String name = dp.getAddress().getHostName();

        System.out.println("ip为:" + ip + ",主机名为:" + name + "的人,发送了数据:" + new String(data, 0, len));

        // 6. 释放资源
        ms.close();

    }
}

(三)、广播

广播用于一个主机对整个局域网上所有主机上的数据通信

广播地址:255.255.255.255

1、实现步骤

发送端
    1. 创建发送端Socket对象(DatagramSocket)
    2. 创建存储数据的箱子,将广播地址封装进去
    3. 发送数据
    4. 释放资源


接收端
    1. 创建接收端的Socket对象(DatagramSocket)
    2. 创建一个数据包,用于接收数据
    3. 调用DatagramSocket对象的方法接收数据
    4. 解析数据包,并把数据在控制台显示
    5. 关闭接收端

2、示例 
  // 发送端
  public class ClientDemo {
      public static void main(String[] args) throws IOException {
          // 1. 创建发送端Socket对象(DatagramSocket)
          DatagramSocket ds = new DatagramSocket();
  		  // 2. 创建存储数据的箱子,将广播地址封装进去
          String s = "广播 hello";
          byte[] bytes = s.getBytes();
          InetAddress address = InetAddress.getByName("255.255.255.255");
          int port = 10000;
          DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
  		  // 3. 发送数据
          ds.send(dp);
  		  // 4. 释放资源
          ds.close();
      }
  }
  
  // 接收端
  public class ServerDemo {
      public static void main(String[] args) throws IOException {
          // 1. 创建接收端的Socket对象(DatagramSocket)
          DatagramSocket ds = new DatagramSocket(10000);
          // 2. 创建一个数据包,用于接收数据
          DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
          // 3. 调用DatagramSocket对象的方法接收数据
          ds.receive(dp);
          // 4. 解析数据包,并把数据在控制台显示
          byte[] data = dp.getData();
          int length = dp.getLength();
          System.out.println(new String(data,0,length));
          // 5. 关闭接收端
          ds.close();
      }
  }

六、TCP通信程序

Java对基于TCP协议的的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。
Java为客户端提供了Socket类,为服务器端提供了ServerSocket类

(一)、TCP发送数据

1、构造方法
  • Socket(InetAddress address,int port):创建流套接字并将其连接到指定IP指定端口号     
  • Socket(String host, int port) :创建流套接字并将其连接到指定主机上的指定端口号 
2、相关方法
  • InputStream  getInputStream():返回此套接字的输入流 
  • OutputStream getOutputStream():返回此套接字的输出流 
3、示例
public class Client {
    public static void main(String[] args) throws IOException {
        //1. 创建客户端Socket对象
        //    在创建对象的同时会连接服务端
        //    如果连接不上,代码会报错
        Socket socket = new Socket("localhost", 12345);

        //2. 从连接通道中获取输出流
        OutputStream os = socket.getOutputStream();

        //3. 写出数据
        os.write("hello".getBytes());

        //4. 释放资源
        os.close();
        socket.close();
    }
}

(二)、TCP接收数据

1、构造方法
  • ServletSocket(int port):创建绑定到指定端口的服务器套接字
2、相关方法
  • Socket accept():监听要连接到此的套接字并接受它 
3、注意事项

  1. accept方法是阻塞的,作用就是等待客户端连接
  2. 客户端创建对象并连接服务器,此时是通过三次握手协议,保证跟服务器之间的连接
  3. 针对客户端来讲,是往外写的,所以是输出流。针对服务器来讲,是往里读的,所以是输入流
  4. read方法也是阻塞的
  5. 客户端在关流的时候,还多了一个往服务器写结束标记的动作
  6. 最后一步断开连接,通过四次挥手协议保证连接终止 

4、示例
public class Server {
    public static void main(String[] args) throws IOException {
        //1. 创建对象ServerSocket
        ServerSocket serverSocket = new ServerSocket(12345);

        //2. 监听客户端的连接
        Socket socket = serverSocket.accept();

        //3. 从连接通道中获取输入流
        InputStream is = socket.getInputStream();

        //4. 读取数据
        byte[] bytes = new byte[1024];
        int len;
        while ((len = is.read(bytes)) != -1) {
            System.out.println(new String(bytes, 0, len));
        }

        //5. 释放资源
        is.close();
        socket.close();
    }
}

 (三)、三次握手和四次挥手

 1、三次握手

三次握手是指在TCP/IP协议中,在建立一个TCP连接时,需要进行三次握手的过程。

  1. 客户端向服务器发送一个SYN(同步)包,表示请求建立连接。
  2. 服务器收到客户端的SYN包后,回复一个SYN+ACK(同步+确认)包,表示接受连接请求。
  3. 客户端收到服务器的SYN+ACK包后,再发送一个ACK(确认)包,表示确认连接。

 

2、四次挥手

四次挥手是指在TCP/IP协议中,在断开一个TCP连接时,需要进行四次挥手的过程。

  1. 当一个应用程序或操作系统要关闭TCP连接时,发送一个FIN包,表示不再发送数据。
  2. 接收方收到FIN包后,发送一个ACK包,表示收到了关闭请求。
  3. 接收方等待一段时间(即等待应用程序处理完所有数据),然后发送一个FIN包,表示自己也准备关闭连接。
  4. 发送方收到FIN包后,发送一个ACK包,表示接受关闭请求。此时连接关闭。

  • 33
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值