Bootstrap

4.网络编程

1、目的

  • 传播交流信息
  • TCP:打电话
  • UDP:发短信

2、通信协议:

  • http
  • TCP/IP簇:三次握手(aba),四次挥手(abba)
  • https

3、IP与端口

1.IP地址类:InetAddress、InetSocketAddress
InetAddress inetAddress1 = InetAddress.getLocalHost();
InetAddress inetAddress2 = InetAddress.getByName("");
inetAddress1.getHostName();		//计算机名
inetAddress2.getHostAddress();	//IP地址
2.端口
  • 单个协议下,端口号不能冲突

  • 公有端口0-1023

    • HTTP:80
    • HTTPS:443
    • FTP:21
    • Telent:23
  • 程序注册端口:1024-49151

    • MySQL:3306
    • ORACLE:1521
  • 端口查看的dos命令:

    netstat -ano					#查看所有端口
    netstat -ano |findstr 1521		#查看1521这个端口
    

4、UDP编程实例

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
//使用UDP通信实现接收多条消息,并可以同时接收多个客户端的消息
public class ReceiveDemo02 {
    public static void main(String[] args) throws IOException {
        System.out.println("----服务端启动----");
        //创建接收端的Socket对象,并配置监听端口,端口10000与发送端dp里配置的端口相同
        DatagramSocket socket = new DatagramSocket(10000);
        //创建数据包对象,配置接收数组、数组大小
        DatagramPacket dp = new DatagramPacket(new byte[1024], 1024);
        while (true) {
            //receive会进行线程阻塞
            socket.receive(dp);
            //打印接收的数据,对dp.getData()进行一个实际数据大小的截位
            System.out.println("收到来自" + dp.getAddress().getHostAddress() + "的消息:" + new String(dp.getData(), 0, dp.getLength()));

        }
        //释放资源
        //socket.close();
    }
}
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
//使用UDP通信实现发多条消息
public class SendDemo02 {
    public static void main(String[] args) throws IOException {
        System.out.println("----客户端启动----");
        Scanner scanner = new Scanner(System.in);
        //创建发送端的Socket对象,系统会随机分配一个端口号
        DatagramSocket socket = new DatagramSocket();
        while (true){
            System.out.println("请输入要发送的内容:");
            String next = scanner.next();
            if(next.equals("exit")){
                //释放资源
                socket.close();
                return;
            }
            else {
                //定义存放数据的数组
                byte[] bytes = next.getBytes(StandardCharsets.UTF_8);
                //创建数据包对象,配置发送数据、数据长度、对方IP、对方端口
                DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("127.0.0.1"), 10000);
                //发送数据
                socket.send(dp);
            }
        }
    }
}

5、TCP编程实例

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
//客户端多发消息
public class ClientDemo04 {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        //创建Socket,配置服务端IP与端口
        Socket socket = new Socket("127.0.0.1", 10012);
        //调用socket.getOutputStream()获取输出流,并用DataOutputStream进行包装
        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
        while (true){
            System.out.println("请输入要发送的数据:");
            String next = scanner.next();
            if(next.equals("exit")){
                //关闭流
                dos.close();
                socket.close();
                return;
            }
            else {
                //发送数据
                dos.writeUTF(next);
            }
        }
    }
}
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
//目标:掌握利用线程池优化tcp服务端的方式
public class ServerDemo04 {
    public static void main(String[] args) throws IOException {
        //创建ServerSocket对象,配置监听端口
        ServerSocket serverSocket = new ServerSocket(10012);
        //创建线程池
        final ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3, 5, 60, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        System.out.println("服务端启动成功");
        while (true) {
            //调用serverSocket.accept();,阻塞线程,等待客户端连接
            Socket socket = serverSocket.accept();
            System.out.println(socket.getInetAddress().getHostAddress() + ":" + socket.getPort() + "连接成功");
            //新建线程处理消息接收
            Thread thread = new Thread(() -> {
                //获取socket的流数据,并用DataInputStream进行封装
                try (DataInputStream dis = new DataInputStream(socket.getInputStream())) {
                    while (true) {
                        //打印信息,dis.readUTF()阻塞线程,等待客户端发送消息
                        System.out.println("收到来自" + socket.getInetAddress().getHostAddress() + ":" + socket.getPort() + "的数据: " + dis.readUTF());
                    }
                } catch (Exception e) {
                    //当客户端意外断开时,会出现异常,在此进行手动处理
                    System.out.println(socket.getInetAddress().getHostAddress() + ":" + socket.getPort() + " 断开连接");
                }
            }, socket.getInetAddress().getHostName());
            //将线程添加到线程池,线程池会自己启动线程,不需要单独调用start()
            poolExecutor.execute(thread);
            /*
            //关闭流
            dis.close();
            socket.close();
            serverSocket.close();
            */
        }
    }
}
;