网络编程

网络编程

所谓的“网络编程”,其实就是编写程序,实现同一个网络中的不同设备之间的通信, 实现数据的传递。

机器通信必须要满足的条件

一个网络中的不同设备,如果需要进行通信,必须满足的条件:

  1. 需要知道对方的IP地址。
  2. 需要知道对方的哪一个端口接收数据。
  3. 需要遵循相同的通信协议。

IP地址

IP:Internet Protocol(网络互连协议)。在计算机中,使用IP地址来描述一个上网设备的唯一地址编号。分为IPv4, IPv6
IPv4: 使用4个字节来描述一个IP地址,由四部分组成,每一个部分一个字节。
IPv6: 使用6个字节来描述一个IP地址,由六部分组成。

端口

端口是一个计算机设备在与外界进行通信的数据的出口和入口,端口号:[0, 65535]
常见的端口号:

  • 3306:mysql
  • 1521:oracle
  • 8080:tomcat

通信协议

HTTP/TCP/UDP...

七层网络分层:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

TCP

是一个传输层的通信协议,是一个安全的、面向连接的通信协议。所谓安全,指的是在数据传递的过程中,不会出现数据丢失的情况。
特点:安全的,面向连接的。

面向连接

在TCP中,有两个角色:客户端、服务端。在通信之前,客户端和服务端需要先建立一个安全的连接,数据的传递可以得到保障。

三次握手

在TCP中,连接的建立需要经历如下几个步骤:

  1. 建立连接时,由客户端向服务端发送一个syn 包,syn包中是一个同步序列编号。发送完之后,客户端进入到 SYN_SENT 状态,等待服务端确认。
  2. 服务端收到syn包之后,服务端必须确认客户端的syn包信息,同时自己也发送一个syn包给客户端,即SYN_ACK包。服务端进入到SYN_RECV状态。
  3. 客户端在接收到SYN_ACK包之后,向服务端回复一个ACK 包。此时客户端和服务端都会进入到TCP连接成功状态。SATABLISHED。

几个常见的类

  • InetAddress:是一个用来描述IP地址的类。
  • Socket:套接字类,描述TCP中的客户端。
  • ServerSocket:描述TCP中的服务端。
  • DatagramSocket:描述UDP中的需要通信的设备。

InetAddress练习

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        try {
            //获取本机
            InetAddress localHost=InetAddress.getLocalHost();
            System.out.println(localHost);//DESKTOP-1E1HCB6/192.168.131.1   主机名/Ip地址
            //通过主机名获取一个主机
            InetAddress host1=InetAddress.getByName("DESKTOP-1E1HCB6");
            System.out.println(host1);//DESKTOP-1E1HCB6/192.168.131.1
            //通过一个IP地址字符串获取主机
            InetAddress host2=InetAddress.getByName("192.168.131.1");
            System.out.println(host2);//       /192.168.131.1
            //通过域名来获取主机
            InetAddress host3=InetAddress.getByName("www.baidu.com");//www.baidu.com/183.232.231.174
            System.out.println(host3);
            //通过域名获取所有主机
            InetAddress[] allByName = InetAddress.getAllByName("www.baidu.com");
            //www.baidu.com/183.232.231.174
            //www.baidu.com/183.232.231.172
            for (InetAddress inetAddress : allByName) {
                System.out.println(inetAddress);
            }
            //通过一个IP地址,获取一个主机。IP地址存入到一个byte数组中,若越界就强转
            InetAddress byAddress = InetAddress.getByAddress(new byte[]{(byte) 192, (byte) 168, (byte) 131, 1});
            System.out.println(byAddress);//     /192.168.131.1


            //通过一个主机来获取主机姓名
            System.out.println(localHost.getHostName());//DESKTOP-1E1HCB6
            //通过一个主机来获取IP地址字符串
            System.out.println(localHost.getHostAddress());//192.168.131.1
            //通过一个主机来获取IP地址的字节数组
            byte[] address = localHost.getAddress();
            System.out.println(Arrays.toString(address));//  [-64, -88, -125, 1]
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

客户端和服务器端进行通信1:客户端将hello,world!发送给服务器端

服务器端
先启动服务器端再启动客户端

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.Scanner;

/**
 * @Author 昊
 * @Create 2020/5/6 21:57
 * @Description
 */
public class Server {
    public static void main(String[] args) {
        //ServerSocket(int port):开启一个服务器端,监听某一个端口
        //ServerSocket用于描述服务器端程序
        //port:端口号
        try(ServerSocket serverSocket=new ServerSocket(9527)){
            //接收套接字并开始监听
            //这个方法会阻塞当前线程,直至建立连接
            Socket accept = serverSocket.accept();
            //显示客户端信息
            InetAddress localAddress = accept.getLocalAddress();
            System.out.printf("客户端%s[%s]对您说:",localAddress.getHostName(),localAddress.getHostAddress());
            //获取输入流
            InputStream inputStream = accept.getInputStream();
//            byte[] array=new byte[1024];
//            int len=0;
//            while ((len=inputStream.read(array))!=-1){
//               String s=new String(array,0,len);
//                System.out.println(s);
//            }
            Scanner scanner=new Scanner(inputStream);
            while (scanner.hasNextLine()){
                System.out.println(scanner.nextLine());
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

客户端

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

/**
 * @Author 昊
 * @Create 2020/5/6 21:57
 * @Description
 */
public class Client {
    public static void main(String[] args) {
        //Socket用来描述客户端主程序
        //port:端口号
        //端口范围是0--65535
        // 0-1023通常会被系统占用,最好使用1024-65535
        try(Socket socket=new Socket(InetAddress.getLocalHost(),9527)){
            //将数据发送给服务器端
            //首先获取输出流
            OutputStream outputStream = socket.getOutputStream();
            //写入数据
            outputStream.write("hello,world!".getBytes());
            //写入一次flush一下
            outputStream.flush();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

客户端和服务器端进行通信2:客户端将控制台输入的信息发送给服务器端

服务器端
先启动服务器端再启动客户端

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.Scanner;

/**
 * @Author 昊
 * @Create 2020/5/6 21:57
 * @Description
 */
public class Server {
    public static void main(String[] args) {
       try(ServerSocket serverSocket=new ServerSocket(9527)){
           Socket accept = serverSocket.accept();
           InetAddress localAddress = accept.getLocalAddress();
           System.out.printf("客户端%s[%s]向您发送了:",localAddress.getHostName(),localAddress.getHostAddress());
           InputStream inputStream = accept.getInputStream();
//           Scanner scanner=new Scanner(inputStream);
//           while (true){
//               String msg = scanner.nextLine();
//               System.out.println(msg);
//               if(msg.matches("88|886|bye|Bye|拜拜")){
//                   break;
//               }
//           }

           while (true){
               byte[] array=new byte[1024];
               int len=0;
               len=inputStream.read(array);
               String msg=new String(array,0,len);
               System.out.println(msg);
               if(msg.matches("88|886|bye|Bye|拜拜")){
                   break;
               }
           }
       }catch (IOException e){
           e.printStackTrace();
       }
    }
}

客户端

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

/**
 * @Author 昊
 * @Create 2020/5/6 21:57
 * @Description
 */
public class Client {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        //Socket用于描述客户端程序
        try(Socket socket=new Socket(InetAddress.getLocalHost(),9527)){
            //获取输出liu
            OutputStream outputStream = socket.getOutputStream();
            while (true){
                //从控制台获取信息
                String line = scanner.nextLine();
                //拼接换行符
                String msg=line+"\n";
                //将信息输出
                //若服务器用的Scanner
                //outputStream.write(msg.getBytes());
                //若服务器端用的是byte数组
                outputStream.write(line.getBytes());
                //flush一下
                outputStream.flush();

                //终止条件
                if(line.matches("88|886|bye|Bye|拜拜")){
                    break;
                }
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

上一篇:网络编程


下一篇:JAVA 网络编程 InetAddress 和端口号