Java 网络编程

04-10 1400阅读

网络编程

  • 一、了解网络
    • 网络的概念
    • 二、网络编程的三要素
      • 网络模型
        • OSI参考模型
        • TCP/IP参考模型
        • IP地址
          • IP地址的表示方法
          • IP地址的分类
          • 特殊的IP地址
          • IP地址所对应的对象(InetAddress)
          • 端口
          • 传输协议
          • 三、Socket套接字
            • 基于TCP协议的Socket编程
            • Socket中实现对象的传递
            • 基于UDP协议的Socket编程

              一、了解网络

              网络的概念

              • 网络:一组相互连接的计算机

                1、多台计算机组成。

                2、使用物理线路进行连接。

                Java 网络编程

                二、网络编程的三要素

                1. IP地址:唯一标识网络上的每台计算机;是两台计算机之间通信的必备要素。
                2. 端口号:计算机中应用的标号:代表一个应用程序);0-1024系统使用或保留端口,有效端口0-65536.
                3. 通信协议:通信的规则,包含TCP和UDP。

                  Java 网络编程

                1. 网络中的每台计算机都有一个唯一的IP地址,网络通过IP地址进行通信。
                2. 计算机A使用QQ与外界交流,那么计算机B的使用者只能通过QQ去解析对方发来的信息,计算机中有那么多的应用程序,使用数字来对这些网络应用程序做标识,这些数字形象的称之为端口号。
                3. 通信之间必须使用相同的规则,这些规则叫协议,国际通用协议TCP/UDP。

                网络模型

                OSI参考模型

                开放系统互连参考模型(Open System Interconnect)

                Java 网络编程

                TCP/IP参考模型

                传输控制/国际协议(Transfer Controln Protocol/Internet Protocol)

                Java 网络编程

                IP地址

                IP地址的表示方法

                IP地址:32位,由4个8位二进制数组成。

                IP表示方法:点分十进制。

                Java 网络编程

                IP地址=网络ID+主机ID

                • 网络ID:标识计算机或网络设备所在的网段。
                • 主机ID:标识特定主机或网络设备。

                  IP地址的分类

                  地址类用于指定网络ID并在网络ID和主机ID之间提供分隔方法。

                  IANA负责分配A、B、C类网络地址,具体主机地址由机构组织自行分配。

                  IP地址类分类:

                  1. A类:一个A类IP地址由1字节的网络地址和3字节主机地址组成,它主要为大型网络而设计的,网络地址的最高位必须是“0”, 地址范围从1.0.0.0 到127.0.0.0)。可用的A类网络有127个,每个网络能容纳16777214个主机。
                  2. B类:一个B类IP地址由2个字节的网络地址和2个字节的主机地址组成,网络地址的最高位必须是“10”,地址范围从128.0.0.0到191.255.255.255。可用的B类网络有16382个,每个网络能容纳6万多个主机 。
                  3. C类:一个C类IP地址由3字节的网络地址和1字节的主机地址组成,网络地址的最高位必须是“110”。范围从192.0.0.0到223.255.255.255。C类网络可达209万余个,每个网络能容纳254个主机。
                  4. D类: D类IP地址是一个专门保留的地址。它并不指向特定的网络,目前这一类地址被用在多点广播(Multicast)中。多点广播地址用来一次寻址一组计算机,它标识共享同一协议的一组计算机。224.0.0.0到239.255.255.255用于多点广播 。
                  5. E类:以“llll0”开始,为将来使用保留。240.0.0.0到255.255.255.254,255.255.255.255用于广播地址。

                  注:在IP地址3种主要类型里,各保留了3个区域作为私有地址,其地址范围如下:

                  A类地址:10.0.0.0~10.255.255.255

                  B类地址:172.16.0.0~172.31.255.255

                  C类地址:192.168.0.0~192.168.255.255

                  特殊的IP地址

                  0.0.0.0:本机。

                  127.0.0.1:本机回环地址,用于本机测试。

                  255.255.255.255:当前子网,一般用于向当前子网广播信息。

                  IP地址所对应的对象(InetAddress)

                  Java 网络编程

                  方法描述
                  public static InetAddress getLocalhost( )获取主机名和IP地址
                  public String getHostAddress( )获取IP地址
                  public String getHostName( )获取主机名
                  public static InetAddress getByName(String host)根据主机名获得IP地址

                  示例代码:

                  public class InteAddressDemo {
                      public static void main(String[] args) throws UnknownHostException {
                          InetAddress localHost = InetAddress.getLocalHost();
                          System.out.println(localHost);
                          InetAddress inetAdd = InetAddress.getByName("www.baidu.com");
                          System.out.println(inetAdd);
                          System.out.println(inetAdd.getHostAddress());
                          System.out.println(inetAdd.getHostName());
                      }
                  }
                  /*  输出的结果是:
                  	// 此行会输出你的主机名和IP地址我就不漏出我的主机命和IP地址了
                  	www.baidu.com/183.2.172.42
                  	183.2.172.42
                  	www.baidu.com
                  */
                  

                  端口

                  端口:port

                  端口是虚拟的概念,并不是说在主机上真的有若干个端口。通过端口,可以在一个主机上运行多个网络应用程序。

                  传输协议

                  • UDP:相当于发短信(有字数限制),不需要建立连接,数据报的大小在64k内,效率较高,但不安全,容易丢包。
                  • TCP:相当于打电话,需要建立连接,效率相对比较低,数据传输安全,三次握手完成。(点名–》答到–》确认)

                    三、Socket套接字

                    • 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个Socket。
                    • Java中使用Socket完成TCP程序的开发,使用此类可以方便的建立可靠的、双向的、持续性的、点对点的通讯连接。
                    • 在Socket的程序开发中,服务器端使用ServerSocket等待客户端的连接,对于Java的网络程序来讲,每个客户端都使用一个Socket对象表示。

                      Java 网络编程

                      基于TCP协议的Socket编程

                      进行网络通信时,Socket需要借助数据流来完成数据的传递工作。

                      Java 网络编程Java 网络编程

                      演示案例: 互相传输一句话。

                      服务器端:

                      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 {
                              //创建serverSocket对象
                              ServerSocket serverSocket = new ServerSocket(10000);
                              //获取服务端的套接字对象
                              Socket socket = serverSocket.accept();
                              //--------------------接收客户端的输入---------------
                              //获取输入流对象
                              InputStream inputStream = socket.getInputStream();
                              byte[] buf = new byte[1024];
                              int length = inputStream.read(buf);
                              System.out.println("客户端传输的数据是:" + new String(buf,0,length));
                              //------------------返回客户端数据------------------
                              OutputStream outputStream = socket.getOutputStream();
                              outputStream.write("你好,收到".getBytes());
                              //关闭流操作
                              outputStream.close();
                              inputStream.close();
                              socket.close();
                              serverSocket.close();
                          }
                      }
                      // 输出的结果是:
                      // 客户端传输的数据是:hello java
                      

                      客户端:

                      import java.io.IOException;
                      import java.io.InputStream;
                      import java.io.OutputStream;
                      import java.net.Socket;
                      public class Client {
                          public static void main(String[] args) throws IOException {
                              //创建客户端的套接字
                              Socket client = new Socket("127.0.0.1",10000);
                              //------------------------向外进行输出------------------
                              //获取输出流对象
                              OutputStream outputStream = client.getOutputStream();
                              //数据输出
                              outputStream.write("hello java".getBytes());
                              //------------------------接收服务端返回的消息-------------
                              //获取输入流对象
                              InputStream inputStream = client.getInputStream();
                              byte[] buf = new byte[1024];
                              int length = inputStream.read(buf);
                              System.out.println("服务端的响应数据是:" + new String(buf,0,length));
                              //关闭流操作
                              inputStream.close();
                              outputStream.close();
                              client.close();
                          }
                      }
                      // 输出的结果是:
                      // 服务端的响应数据是:你好,收到
                      

                      演示案例: 客户端向服务器端提交一张照片。

                      服务器端:

                      import java.io.*;
                      import java.net.ServerSocket;
                      import java.net.Socket;
                      public class PicServer {
                          public static void main(String[] args) throws IOException {
                              //创建服务端对象,开放端口
                              ServerSocket serverSocket = new ServerSocket(10086);
                              //创建服务器的Socket
                              Socket server = serverSocket.accept();
                              //获取输入流对象
                              InputStream inputStream = server.getInputStream();
                              //创建文件输出流对象
                              FileOutputStream fileOutputStream = new FileOutputStream("2.jpg");
                              int temp = 0;
                              while ((temp = inputStream.read()) != -1){
                                  fileOutputStream.write(temp);
                              }
                              //添加流输出完成的标志
                              server.shutdownInput();
                              //上传图片结束之后给予客户端响应
                              OutputStream outputStream = server.getOutputStream();
                              outputStream.write("上传成功".getBytes());
                              server.shutdownOutput();
                              //关闭流
                              outputStream.close();
                              fileOutputStream.close();
                              inputStream.close();
                              server.close();
                              serverSocket.close();
                          }
                      }
                      

                      客户端:

                      import java.io.FileInputStream;
                      import java.io.InputStream;
                      import java.io.OutputStream;
                      import java.net.Socket;
                      public class PicClient {
                          public static void main(String[] args) throws Exception {
                              //创建图片的输入流对象
                              FileInputStream fileInputStream = new FileInputStream("1.jpg");
                              //创建Socket
                              Socket client = new Socket("localhost",10086);
                              //获取输出流对象
                              OutputStream outputStream = client.getOutputStream();
                              int temp = 0;
                              while ((temp = fileInputStream.read()) != -1){
                                  outputStream.write(temp);
                              }
                              client.shutdownOutput();
                              //接收服务端的响应
                              InputStream inputStream = client.getInputStream();
                              byte[] buf = new byte[1024];
                              int length = inputStream.read(buf);
                              System.out.println(new String(buf,0,length));
                              client.shutdownInput();
                              //关闭流操作
                              inputStream.close();
                              outputStream.close();
                              client.close();
                              fileInputStream.close();
                          }
                      }
                      

                      注意: 要先启动服务器端再启动客户端。

                      Socket中实现对象的传递

                      如何传递对象信息呢?

                      String info = "用户名:Lisi;用户密码:123456";
                      outputStream.write(info.getBytes());
                      

                      序列化

                      User user = new User();// User是用户类
                      user.setLoginName("Lisi");
                      user.setPassword("123456");
                      oos.writeObject(user);
                      

                      演示案例: 实现用户登录。

                      • 方法一

                        用户类:

                        import java.io.Serial;
                        import java.io.Serializable;
                        public class User implements Serializable {
                            @Serial// 指定序列化版本号
                            private static final long serialVersionUID = -8254223107980283532L;
                            private String username;
                            private String password;
                            public User() {
                            }
                            public User(String username, String password) {
                                this.username = username;
                                this.password = password;
                            }
                            public String getUsername() {
                                return username;
                            }
                            public void setUsername(String username) {
                                this.username = username;
                            }
                            public String getPassword() {
                                return password;
                            }
                            public void setPassword(String password) {
                                this.password = password;
                            }
                        }
                        

                        服务器端:

                        import java.io.DataOutputStream;
                        import java.io.InputStream;
                        import java.io.ObjectInputStream;
                        import java.net.ServerSocket;
                        import java.net.Socket;
                        public class LoginServer {
                            public static void main(String[] args) throws Exception {
                                ServerSocket serverSocket = new ServerSocket(10000);
                                while (true){
                                    Socket server = serverSocket.accept();
                                    //获取输入流对象
                                    InputStream inputStream = server.getInputStream();
                                    //需要使用ObjectInputStream对象
                                    ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
                                    User user = (User) objectInputStream.readObject();
                                    String str = "";
                                    if ("lyf".equals(user.getUsername()) && "lyf".equals(user.getPassword())){
                                        str = "登录成功";
                                        System.out.println("欢迎您:" + user.getUsername());
                                    } else {
                                        str = "登录失败";
                                    }
                                    //截断输入流
                                    server.shutdownInput();
                                    //给客户端响应
                                    DataOutputStream dataOutputStream = new DataOutputStream(server.getOutputStream());
                                    dataOutputStream.writeUTF(str);
                                    server.shutdownOutput();
                                    //关闭流操作
                                    dataOutputStream.close();
                                    objectInputStream.close();
                                    inputStream.close();
                                    server.close();
                                }
                            }
                        }
                        // 输出的结果是:
                        // 欢迎您:lyf
                        

                        客户端:

                        import java.io.DataInputStream;
                        import java.io.IOException;
                        import java.io.ObjectOutputStream;
                        import java.io.OutputStream;
                        import java.net.Socket;
                        import java.util.Scanner;
                        public class LoginClient {
                            public static void main(String[] args) throws IOException {
                                Socket client = new Socket("localhost",10000);
                                OutputStream outputStream = client.getOutputStream();
                                //完成用户登录功能,需要传输一个user对象
                                User user = getUser();
                                ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
                                objectOutputStream.writeObject(user);
                                //调用shutdown方法告诉对方传输完成
                                client.shutdownOutput();
                                //接收响应
                                DataInputStream dataInputStream = new DataInputStream(client.getInputStream());
                                String str = dataInputStream.readUTF();
                                System.out.println(str);
                                //关闭流操作
                                dataInputStream.close();
                                objectOutputStream.close();
                                outputStream.close();
                                client.close();
                            }
                            public static User getUser(){
                                Scanner scanner = new Scanner(System.in);
                                System.out.println("请输入用户名:");
                                String username = scanner.nextLine();
                                System.out.println("请输入密码:");
                                String password = scanner.nextLine();
                                return new User(username,password);
                            }
                        }
                        /*
                        请输入用户名:
                        lyf
                        请输入密码:
                        lyf
                        输入正确的用户名和密码后会返回:登录成功
                        */
                        
                        • 方法二

                          用户类:

                          import java.io.Serial;
                          import java.io.Serializable;
                          public class User implements Serializable {
                              @Serial// 指定序列化版本号
                              private static final long serialVersionUID = -8254223107980283532L;
                              private String username;
                              private String password;
                              public User() {
                              }
                              public User(String username, String password) {
                                  this.username = username;
                                  this.password = password;
                              }
                              public String getUsername() {
                                  return username;
                              }
                              public void setUsername(String username) {
                                  this.username = username;
                              }
                              public String getPassword() {
                                  return password;
                              }
                              public void setPassword(String password) {
                                  this.password = password;
                              }
                          }
                          

                          服务器端:

                          import java.net.ServerSocket;
                          import java.net.Socket;
                          public class LoginServer2 {
                              public static void main(String[] args) throws Exception {
                                  ServerSocket serverSocket = new ServerSocket(10000);
                                  while (true){
                                      Socket socket = serverSocket.accept();
                                      LoginThread loginThread = new LoginThread(socket);
                                      new Thread(loginThread).start();
                                  }
                              }
                          }
                          // 输出的结果是:
                          // 欢迎您:lyf
                          

                          线程类:

                          import java.io.DataOutputStream;
                          import java.io.IOException;
                          import java.io.ObjectInputStream;
                          import java.net.Socket;
                          public class LoginThread implements Runnable{
                              private Socket socket;
                              public LoginThread(Socket socket) {
                                  this.socket = socket;
                              }
                              @Override
                              public void run() {
                                  ObjectInputStream objectInputStream = null;
                                  DataOutputStream dataOutputStream = null;
                                  try {
                                      objectInputStream = new ObjectInputStream(socket.getInputStream());
                                      User user = (User) objectInputStream.readObject();
                                      String str = "";
                                      if ("lyf".equals(user.getUsername()) && "lyf".equals(user.getPassword())){
                                          str = "登录成功";
                                          System.out.println("欢迎您:" + user.getUsername());
                                      } else {
                                          str = "登录失败";
                                      }
                                      socket.shutdownInput();
                                      dataOutputStream = new DataOutputStream(socket.getOutputStream());
                                      dataOutputStream.writeUTF(str);
                                      socket.shutdownOutput();
                                  } catch (IOException e) {
                                      throw new RuntimeException(e);
                                  } catch (ClassNotFoundException e) {
                                      throw new RuntimeException(e);
                                  }finally {
                                      try {
                                          dataOutputStream.close();
                                          objectInputStream.close();
                                          socket.close();
                                      } catch (IOException e) {
                                          throw new RuntimeException(e);
                                      }
                                  }
                              }
                          }
                          

                          客户端:

                          import java.io.DataInputStream;
                          import java.io.IOException;
                          import java.io.ObjectOutputStream;
                          import java.io.OutputStream;
                          import java.net.Socket;
                          import java.util.Scanner;
                          public class LoginClient {
                              public static void main(String[] args) throws IOException {
                                  Socket client = new Socket("localhost",10000);
                                  OutputStream outputStream = client.getOutputStream();
                                  //完成用户登录功能,需要传输一个user对象
                                  User user = getUser();
                                  ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
                                  objectOutputStream.writeObject(user);
                                  //调用shutdown方法告诉对方传输完成
                                  client.shutdownOutput();
                                  //接收响应
                                  DataInputStream dataInputStream = new DataInputStream(client.getInputStream());
                                  String str = dataInputStream.readUTF();
                                  System.out.println(str);
                                  //关闭流操作
                                  dataInputStream.close();
                                  objectOutputStream.close();
                                  outputStream.close();
                                  client.close();
                              }
                              public static User getUser(){
                                  Scanner scanner = new Scanner(System.in);
                                  System.out.println("请输入用户名:");
                                  String username = scanner.nextLine();
                                  System.out.println("请输入密码:");
                                  String password = scanner.nextLine();
                                  return new User(username,password);
                              }
                          }
                          /*
                          请输入用户名:
                          lyf
                          请输入密码:
                          lyf
                          输入正确的用户名和密码后会返回:登录成功
                          */
                          

                          上述两种方法都能实现客户端与服务器端之间的用户登录效果。

                          基于UDP协议的Socket编程

                          TCP和UDP之间的区别:

                          1、TCP协议通信双方需要建立连接,而UDP协议通信双方不需要建立连接。

                          2、TCP协议通信双方连接建立时双方存在主次之分,而UDP协议通信双方完全平等。

                          Java 网络编程

                          示例代码:

                          服务器端:

                          import java.net.DatagramPacket;
                          import java.net.DatagramSocket;
                          public class UDPServer {
                              public static void main(String[] args) throws Exception {
                                  DatagramSocket datagramSocket = new DatagramSocket(10001);
                                  byte[] buf = new byte[1024];
                                  //用来接收传输过来的数据
                                  DatagramPacket datagramPacket = new DatagramPacket(buf,buf.length);
                                  //利用创建好的数据报包对象来接收数据
                                  datagramSocket.receive(datagramPacket);
                                  //打印输出信息
                                  System.out.println(new String(datagramPacket.getData(),0,datagramPacket.getLength()));
                                  datagramSocket.close();
                              }
                          }
                          // 接收客户端控制台上传输过来的数据并打印
                          

                          客户端:

                          import java.net.DatagramPacket;
                          import java.net.DatagramSocket;
                          import java.net.InetAddress;
                          import java.util.Scanner;
                          public class UDPClient {
                              public static void main(String[] args) throws Exception {
                                  //创建udp通信的socket
                                  DatagramSocket datagramSocket = new DatagramSocket(10000);
                                  //从控制台读取数据
                                  Scanner scanner = new Scanner(System.in);
                                  String str = scanner.nextLine();
                                  DatagramPacket datagramPacket = new DatagramPacket(str.getBytes(),str.getBytes().length, InetAddress.getByName("localhost"),10001);
                                  datagramSocket.send(datagramPacket);
                                  datagramSocket.close();
                              }
                          }
                          // 在客户端的控制台上输入数据
                          
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]