Java高级编程–网络编程

Java高级编程–网络编程

1.IP地址

1.1IP地址介绍

  • 什么是IP地址?为什么需要IP地址?
    • 两台计算机通信, 双方都必须有地址->IP地址
    • 唯一标识网络上的每一台计算机

1.2IP地址的组成

  • 32位,由4个8位二进制数组成

  • IP地址 = 网络地址 +主机地址

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

在这里插入图片描述

1.3IP地址的配置和检测

  • 查看IP地址,检测网络是否畅通
    • 查看本机的IP地址<ipconfig>
    • 测试网络是否通畅<ping 目标IP地址>

1.4DNS域名解析

  • 访问网站时,为什么输入网址而不是IP地址?

    DNS:Domain Name System,域名系统

2.网络服务器

通常指在网络环境下,具有较高计算能力,能够提供用户服务功能的计算机

3.网络通信协议

为了在网络中不同的计算机之间进行通信而建立的规则、标准或约定的集合

在这里插入图片描述

五层协议

  • 物理层:基于电器特性的高低电压(电信号)高电压代表1低电压代表0
  • 数据链路层:定义电信号的分组方式
  • 网络层:引入一套新的地址来区分不同的广播域
  • 传输层:端口到端口的连接通信
  • 应用层(应用层,表示层,会话层):规定了数据的传输格式http,ftp

4.Socket

4.1什么是Socket?

  • Socket的底层机制复杂,Java平台提供了一些简单的API,可以更简单有效的使用Socket开发而无需了解底层机制
  • 通信链路的端点就被称为“套接字”(英文名Socket)
  • 是提供给应用程序的接口

4.2java.net包

  • Socket
  • ServerSocket
  • DatagramPacket
  • DatagramSocket
  • InetAddress

4.3基于TCP协议的Socket编程

  • 基于TCP协议的Socket网络通信

    • 用来实现双向安全连接网络通信
  • Socket通信模型

    • 进行网络通信时,Socket需要借助数据流来完成数据的传递工作
  • 三次握手和四次挥手

在这里插入图片描述

  • 三次握手 (建立连接) ps:假设A是客户端,B是服务器

    1.(A->B)携带syn数据包

    A问B你能收到我的消息吗?k

    2.(B->A)如果B同意连接则回复消息同意,向A发送syn+ack

    B回答我收到了,你能收到我的消息吗?k

    3.(A->B)A在向B发送ack数据包

    A回答我收到了,开始通信

  • 为什么不能用两次握手?

    • 服务器收到客户端的SYN并回复SYN-ACK后,只能确认自己可收、可发。但服务器无法确认客户端是否能正常接收数据(因为客户端未回复ACK),可能会导致连接不可靠、资源浪费或数据错误。

    在这里插入图片描述

  • 四次挥手(关闭连接) ps:假设A是客户端,B是服务器

    1.(A–>B)发送fin包

    我要关闭,等你确认

    2.(B–>A)发送ack包,此时B会进入等待关闭状态

    B说稍等,等待关闭。

    3.(B–>A)发送fin包,进入最后确认状态。

    确认完成,可以关闭了。

    4.(A–>B)A收到后回复ack包,进入超时等待状态。等待结束关闭A,B收到ack后立即关闭连接。

    A确认关闭,B立即关闭。

  • 为什么不能用三次挥手?

    • 去掉第四次挥手(客户端的ACK),服务端发送 FIN 后,如果没有收到客户端的 ACK,服务端会一直处于最后确认状态,服务端会认为客户端没有收到 FIN,从而无法确定连接已经完全关闭。TCP协议有重传机制,如果服务端没有收到客户端的 ACK,它会重新发送 FIN。如果去掉第四次挥手,服务端会一直重传 FIN,直到超时,这会导致不必要的资源浪费。
  • Socket网络编程一般可以分成如下步骤

在这里插入图片描述

package com.hz.ch09.tcplx;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
/**
 * 客户端(向外写数据)
 */
public class ClientSocketTCP {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream os = null;
        OutputStreamWriter osw = null;
        Scanner scanner = new Scanner(System.in);
        try {
            //1.创建客户端Socket对象
            socket = new Socket("192.168.29.12", 8080);
            //2.从Socket中获取一个输出流,往服务器上写数据
            os = socket.getOutputStream();
            //3.将字节输出流转为字符输出流
            osw = new OutputStreamWriter(os);
            //4.写数据
            System.out.println("请输入要发送的内容");
            String data = scanner.nextLine();
            osw.write(data);
            //5.释放资源
            osw.close();
            os.close();
            socket.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

package com.hz.ch09.tcplx;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务器端
 */
public class ServerSocketTCP {
    public static void main(String[] args) {

        try {
            System.out.println("服务器启动了");
            //1.创建服务器端的ServerSocket对象
            ServerSocket    serverSocket = new ServerSocket(8080);
            //2.调用accept()方法接收客户端的Socket对象
            Socket socket = serverSocket.accept();
            //3.获取输入流
            InputStream is = socket.getInputStream();
            //4.将字节流转换为字符流
            InputStreamReader isr = new InputStreamReader(is);
            char[] chars = new char[1024];
            int len = 0;
            while ((len = isr.read(chars)) != -1) {
                String s = new String(chars, 0, len);
                System.out.println(s);
            }
            //5.释放资源
            isr.close();
            is.close();
            socket.close();
            serverSocket.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

}

4.4Socket中实现对象的传递

  • 序列化

    package com.hz.ch09.tcplx3;
    
    import java.io.Serializable;
    
    public class UserInfo implements Serializable {
        private  String userName;
        private String pwd;
    
        public UserInfo() {
        }
    
        public UserInfo(String userName, String pwd) {
            this.userName = userName;
            this.pwd = pwd;
        }
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public String getPwd() {
            return pwd;
        }
    
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    
        @Override
        public String toString() {
            return "UserInfo{" +
                    "userName='" + userName + '\'' +
                    ", pwd='" + pwd + '\'' +
                    '}';
        }
    }
    
    
    package com.hz.ch09.tcplx3;
    
    import java.io.*;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class ClientSocketTCP3 {
        public static void main(String[] args) {
            try {
                //1.创建一个Socket对象,指定服务器的IP地址和端口号
                Socket socket=new Socket("127.0.0.1",8080);
                //2.获取输出流,向服务器端发送信息
                OutputStream os=socket.getOutputStream();
                ObjectOutputStream oos=new ObjectOutputStream(os);
                oos.writeObject(getUserInfo());
                //3.获取输入流,读取服务器端的回复信息
                InputStream is=socket.getInputStream();
                DataInputStream dis=new DataInputStream(is);
                System.out.println("收到服务器端的回复:"+dis.readUTF());
                //4.关闭资源
                dis.close();
                is.close();
                oos.close();
                os.close();
                socket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
    
        }
        private  static UserInfo getUserInfo(){
            Scanner scanner=new Scanner(System.in);
            System.out.print("请输入用户名:");
            String name=scanner.next();
            System.out.print("请输入密码:");
            String pwd=scanner.next();
            UserInfo userInfo=new UserInfo(name,pwd);
            return userInfo;
    
        }
    
    }
    
    
    package com.hz.ch09.tcplx3;
    
    import java.io.DataOutputStream;
    import java.io.InputStream;
    import java.io.ObjectInputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class ServerSocketTCP3 {
        public static void main(String[] args) {
            try {
                System.out.println("服务器已启动,等待连接......");
                ServerSocket serverSocket = new ServerSocket(8080);
                Socket socket = serverSocket.accept();
                InputStream is = socket.getInputStream();
                ObjectInputStream ois = new ObjectInputStream(is);
                UserInfo userInfo = (UserInfo) ois.readObject();
                System.out.println("收到客户端发来的消息:" + userInfo.toString());
                String s = "登录失败";
                if (check(userInfo)) {
                    s = "登录成功";
                }
                OutputStream os = socket.getOutputStream();
                DataOutputStream dos = new DataOutputStream(os);
                dos.writeUTF(s);
                dos.close();
                os.close();
                ois.close();
                is.close();
                socket.close();
                serverSocket.close();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        public static boolean check(UserInfo userInfo) {
            if ("yy".equals(userInfo.getUserName()) && "0909".equals(userInfo.getPwd())) {
                return true;
            }
            return false;
        }
    
    }
    
    

4.5多线程处理多请求

  • 实现多客户请求
    • 采用多线程的方式
    • 一个专门负责监听的应用主服务程序
    • 一个专门负责处理请求的线程程序
package com.hz.ch09.tcplx6;

import java.io.Serializable;

public class Student implements Serializable {
    private String name;
    private String pwd;

    public Student(String name, String pwd) {
        this.name = name;
        this.pwd = pwd;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}

package com.hz.ch09.tcplx6;

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

public class Client1 {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1", 6666);
            OutputStream os = socket.getOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(os);
            Student student = new Student("杨洋", "0909");
            oos.writeObject(student);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}


package com.hz.ch09.tcplx6;

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

public class Client2 {
    public static void main(String[] args) {
        try {
            Socket socket=new Socket("127.0.0.1",6666);
            OutputStream os = socket.getOutputStream();
            ObjectOutputStream oos=new ObjectOutputStream(os);
            Student student=new Student("陈楚生","0725");
            oos.writeObject(student);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

package com.hz.ch09.tcplx6;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.Socket;

public class StuThread extends Thread {
    private Socket socket;

    public StuThread(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try {
            InputStream inputStream = socket.getInputStream();
            ObjectInputStream ois = new ObjectInputStream(inputStream);
            Student student = (Student) ois.readObject();
            System.out.println(student);
        } catch (Exception e) {
            e.printStackTrace();

        }


    }
}

package com.hz.ch09.tcplx6;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) {
        System.out.println("----------服务器端----------");
        try {
            ServerSocket serverSocket = new ServerSocket(6666);
            while (true){
                Socket socket = serverSocket.accept();
                StuThread stuThread=new StuThread(socket);
                stuThread.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4.6基于UDP协议的Socket编程

TCPUDP
是否连接面向连接面向非连接
传输可靠性可靠不可靠
速度
  • 基于UDP协议的Socket网络编程步骤

在这里插入图片描述

package com.hz.ch09.udplx3;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class Client1 {
    public static void main(String[] args) {
        System.out.println("---------客户端1----------");
        Scanner scanner = new Scanner(System.in);
        DatagramPacket dp = null;
        DatagramSocket ds = null;
        try {
            //通过IP获得inetAddress对象
            InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
            while (true) {
                System.out.print("客户端1请输入要发送的内容:");
                String msg = scanner.next();
                //封装数据包
                dp = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, inetAddress, 8888);
                ds = new DatagramSocket();
                ds.send(dp);
                //准备空数据包
                byte[] bytes = new byte[1024];
                dp = new DatagramPacket(bytes, bytes.length);
                //填充数据包
                ds.receive(dp);
                //解析数据包
                String msg1 = new String(dp.getData(), 0, dp.getLength());
                System.out.println("客户端1收到客户端2回复信息:" + msg1);
                //关闭资源
                ds.close();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

package com.hz.ch09.udplx3;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.util.Scanner;

public class Client2 {
    public static void main(String[] args) {
        System.out.println("---------客户端2----------");
        Scanner scanner = new Scanner(System.in);
        DatagramPacket dp = null;
        DatagramSocket ds = null;
        try {
            ds = new DatagramSocket(8888);
            while (true) {
                //准备空的数据包
                byte[] bytes = new byte[1024];
                dp = new DatagramPacket(bytes, bytes.length);
                //填充数据包
                ds.receive(dp);
                //解析数据包
                String msg = new String(dp.getData(), 0, dp.getLength());
                System.out.println("客户端2收到客户端1的信息:" + msg);
                System.out.print("客户端2请输入要回复的信息:");
                String msg2 = scanner.next();
                //客户端1的地址
                SocketAddress sa = dp.getSocketAddress();
                //封装数据包
                dp = new DatagramPacket(msg2.getBytes(), 0, msg2.getBytes().length, sa);
                //发生数据包
                ds.send(dp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值