网络编程学习

1 网络概括

1.1 网页编程与网络编程

  • 网页编程 : 注重的是上层的应用
  • 网络编程 : 注重是底层数据的传输

1.2 了解

  • IP : 定义节点
  • 端口 : 区分软件
  • URL : 统一资源定位符
  • 协议 : 标准,规范,规则,合同
    • 传输层协议 : 互联网中传输数据需要满足传输层协议,传输变的更加畅通,更安全
      • UDP : 非面向连接,相当于写信, 只管写只管邮,协议简单,不安全,效率高 大小限制不超过60k
      • TCP : 面向连接, 相当于打电话, 安全, 效率较低 ,没有大小限制 ,基于3次握手,四次挥手

1.3 重点

  • 重点 -传输层协议tcp服务端
  • 了解 -分层协议

2 IP

2.1 理解

  • IP : 定义节点,区分节点(互联网中的电子设备都可以通过IP定义)
    分类: IPV4 ->4个字节->32位 IPV6 ->128位
    192.168.0.0~192.168.255.255 非注册IP,供组织内部使用的IP
    127.0.0.1 ->本地IP
    localhost ->本地域名
    IP->域名 : DNS服务器
  • java.net网络包
    InetAddress : 表示IP地址

2.2 代码

public class Class001_IP {
    public static void main(String[] args) throws UnknownHostException {
        //static InetAddress getLocalHost() 返回本地主机的地址。
        InetAddress ip1 = InetAddress.getLocalHost();
        System.out.println(ip1);  //DESKTOP-KHNV6UD/192.168.5.244
        //String getHostAddress() 返回文本表示中的IP地址字符串。
        //String getHostName() 获取此IP地址的主机名。
        System.out.println(ip1.getHostAddress());
        System.out.println(ip1.getHostName());

        //static InetAddress getByName(String host) 根据主机名称确定主机的IP地址。
        InetAddress ip2 = InetAddress.getByName("www.baidu.com");
        System.out.println(ip2);  //www.baidu.com/180.101.49.11
        System.out.println(ip2.getHostAddress());
        System.out.println(ip2.getHostName());
    }
}

3 端口

3.1 理解

  • 端口 : port
    区分软件
  • 0~65535表示端口号 2个字节
  • 统一协议下端口号不能冲突
  • 8000以下端口不建议使用,预留端口号
  • 常见的端口号:
    80 : http
    8080 : tomcat
    1521 : Oracle
    3306 : Mysql
  • InetSocketAddress 此类实现IP套接字地址(IP地址+端口号)

3.2 代码

public class Class002_Port {
    public static void main(String[] args){
        //InetSocketAddress(String hostname, int port) 根据主机名和端口号创建套接字地址。
        //InetSocketAddress(InetAddress addr, int port) 根据IP地址和端口号创建套接字地址。
        InetSocketAddress address = new InetSocketAddress("127.0.0.1",9999);
        System.out.println(address);
        //InetAddress getAddress() 获取 InetAddress 。
        //String getHostName() 获取 hostname 。
        //int getPort() 获取端口号。
        System.out.println(address.getAddress().getHostAddress());
        System.out.println(address.getPort());
    }
}

4 URL

4.1 理解

  • URL : 统一资源定位符,向万维网上的“资源”的指针。
    互联网的三大基石 : URL HTML HTTP

4.2 组成

  • URL组成:
    1.协议 http
    2.域名 www.baidu.com
    3.端口 80
    4.资源 index.html
    5.数据 username=zhangsan&password=123
    6.锚点 #a

4.3 练习

  • url : http://www.baidu.com:80/index.html?username=zhangsan&password=123#a

4.4 代码

public class Class003_URL {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("http://www.baidu.com:80/index.html?username=zhangsan&password=123#a");
        System.out.println(url);
        System.out.println("协议:"+url.getProtocol());//http
        System.out.println("域名:"+url.getHost());//www.baidu.com
        System.out.println("端口:"+url.getPort());//80
        System.out.println("资源:"+url.getFile());///index.html?username=zhangsan&password=123
        System.out.println("文件路径"+url.getPath());///index.html
        System.out.println("数据:"+url.getQuery());//username=zhangsan&password=123
        System.out.println("锚点:"+url.getRef());//a
    }
}

5 UDP

5.1 Socket 套接字

  • 是传输层为应用层开辟的一个小口子,相当于码头,插座
  • 不同协议下Socket实现不同
  • 网络编程确实是面向Socket编程

5.2 UDP

  • DatagramPacket 数据报包
  • DatagramSocket 此类表示用于发送和接收数据报包的套接字。
  • UDP协议下两端(发送端,接收端)是平等,数据基于包裹,基于字节数组

5.3 UDP协议实现基础的发送端

  • 定义我是发送端 DatagramSocket(int port) 构造一个数据报套接字并将其绑定到本地主机上的指定端口。
  • 准备数据
  • 数据打包
  • 发送端发送包裹 void send(DatagramPacket p) 从此套接字发送数据报包。
  • 关闭

5.4 UDP协议实现基础的接收端

  • 定义我是接收端
  • 准备包裹用来接收数据
  • 接收端接收数据
  • 处理数据
  • 关闭

5.5 代码

5.5.1 发送端

public class Class001_Send {
    public static void main(String[] args) throws IOException {
        System.out.println("-----------------发送端---------------------");
        //1.定义我是发送端
        DatagramSocket sendSocket = new DatagramSocket(9999);
        //2.准备数据
        byte[] arr = "你好".getBytes();
        //3.数据打包
        //DatagramPacket(byte[] buf, int length, SocketAddress address) 构造数据报包,用于将长度为 length的数据包发送到指定主机上的指定端口号。
        DatagramPacket packet = new DatagramPacket(arr,0,arr.length,new InetSocketAddress("localhost",9898));
        //4.发送端发送包裹
        sendSocket.send(packet);
        //5.关闭
        sendSocket.close();
    }
}

5.5.2 接收端

public class Class002_Receive {
    public static void main(String[] args) throws IOException {
        System.out.println("-----------------接收端---------------------");
        //1.定义我是接收端
        DatagramSocket receiveSocket = new DatagramSocket(9898);
        //2.准备包裹用来接收数据
        byte[] arr = new  byte[1024];
        DatagramPacket packet = new DatagramPacket(arr,0,arr.length);
        //3.接收端接收数据
        receiveSocket.receive(packet);
        //4.处理数据
        //byte[] getData() 返回数据缓冲区。
        //int getLength() 返回要发送的数据的长度或接收的数据的长度。
        byte[] result = packet.getData();
        int len = packet.getLength();
        System.out.println(new String(result,0,len));

        //5.关闭
        receiveSocket.close();
    }
}

6 TCP

6.1 理解

  • tcp协议下传输数据:
    客户端
    服务器
    基于IO

6.2 发送与接收

6.2.1 tcp协议实现客户端 : 基本流程

  • 构建我是客户端 Socket(String host, int port) IP+端口号指要连接的服务器的IP与端口
  • 基于IO操作
    • 获取输出流
    • 写出
    • 刷出
    • 关闭
  • 关闭

6.2.2 tcp协议实现服务端 : 基本流程

  • 构建我是服务端 ServerSocket(int port)
  • 阻塞式监听 Socket accept() 侦听对此套接字的连接并接受它。
  • IO操作
    • 获取输入流
    • 读入数据
    • 处理数据
    • 关闭
  • 关闭

6.3 代码

6.3.1 发送端

public class Class001_Client {
    public static void main(String[] args) throws IOException {
        System.out.println("----我是客户端---------");
        //1.构建我是客户端 Socket(String host, int port)
        Socket client = new Socket("127.0.0.1", 8989);
        //2.基于IO操作
        DataOutputStream os = new DataOutputStream(client.getOutputStream());
        os.writeUTF("哈哈");
        os.flush();

        //3.关闭
        os.close();
        client.close();
    }
}

6.3.2 接收端

public class Class002_Server {
    public static void main(String[] args) throws IOException {
        System.out.println("----我是服务端---------");
        //1.构建我是服务端  ServerSocket
        ServerSocket server = new ServerSocket(8989);
        //2.阻塞式监听 Socket accept()
        Socket client = server.accept();
        System.out.println("----一个客户端连接成功---------");
        //3.IO操作
        DataInputStream is = new DataInputStream(client.getInputStream());
        String str = is.readUTF();
        System.out.println(str);
        //4.关闭
        is.close();
        client.close();
        server.close();
    }
}

7 用户登录练习

7.1 单用户登录

7.1.1 客户端

  • 构建我是客户端
  • 键盘接收用户名与密码
  • 基于IO操作向服务器发送数据
    • 获取输出流
    • 写出
    • 刷出
    • 关闭
  • 关闭
public class Class003_LoginClient {
    public static void main(String[] args) throws IOException {
        System.out.println("----我是客户端---------");
        //1.构建我是客户端 Socket(String host, int port)
        Socket client = new Socket("127.0.0.1", 8989);
        //2.键盘接收用户名与密码
        BufferedReader rd = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("请输入用户名 : ");
        String username = rd.readLine();
        System.out.println("请输入用户密码 : ");
        String password = rd.readLine();

        //3.基于IO操作
        DataOutputStream os = new DataOutputStream(client.getOutputStream());
        //username=zhangsan&password=123
        os.writeUTF("username="+username+"&password="+password);
        os.flush();

        //3.关闭
        os.close();
        rd.close();
        client.close();
    }
}

7.1.2 服务端

  • 构建我是服务端
  • 阻塞式监听
  • IO操作接收客户端数据
    1)获取输入流
    2)读入数据
    3)处理数据
    4)关闭
  • 关闭
public class Class004_LoginServer {
    public static void main(String[] args) throws IOException {
        System.out.println("----我是服务端---------");
        //1.构建我是服务端  ServerSocket
        ServerSocket server = new ServerSocket(8989);
        //2.阻塞式监听 Socket accept()
        Socket client = server.accept();
        System.out.println("----一个客户端连接成功---------");
        //3.IO操作
        DataInputStream is = new DataInputStream(client.getInputStream());
        String str = is.readUTF();  //username=zhangsan&password=1234    //laopei     1234

        //字符串处理第一种方式 :
        /*String msg = "username="+"laopei"+"&password="+"1234";
        if(msg.equals(str)){
            System.out.println("登录成功");
        }else{
            System.out.println("登录失败");
        }*/

        //字符串处理第二种方式 :
        String uname = "";
        String upwd = "";
        String[] arr = str.split("&");
        for(String s:arr){
            String[] arr2 = s.split("=");
            if("username".equals(arr2[0])){
                uname = arr2[1];
            }else if("password".equals(arr2[0])){
                upwd = arr2[1];
            }
        }
        if("laopei".equals(uname) && "1234".equals(upwd)){
            System.out.println("登录成功");
        }else{
            System.out.println("登录失败");
        }

        //4.关闭
        is.close();
        client.close();
        server.close();
    }
}

7.2 双向登录

7.2.1 客户端

  • 构建我是客户端
  • 键盘接收用户名与密码
  • 基于IO操作向服务器发送数据
  • 基于IO操作接收服务器响应的结果
  • 处理结果
  • 关闭
public class Class005_LoginTwoWayClient {
    public static void main(String[] args) throws IOException {
        System.out.println("----我是客户端---------");
        //1.构建我是客户端 Socket(String host, int port)
        Socket client = new Socket("127.0.0.1", 8989);
        //2.键盘接收用户名与密码
        BufferedReader rd = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("请输入用户名 : ");
        String username = rd.readLine();
        System.out.println("请输入用户密码 : ");
        String password = rd.readLine();

        //3.基于IO操作向服务器发送数据
        DataOutputStream os = new DataOutputStream(client.getOutputStream());
        //username=zhangsan&password=123
        os.writeUTF("username="+username+"&password="+password);
        os.flush();

        //4.基于IO操作接收服务器响应的结果
        DataInputStream is = new DataInputStream(client.getInputStream());
        String result = is.readUTF();
        //5.处理结果
        System.out.println(result);

        //6.关闭
        is.close();
        os.close();
        rd.close();
        client.close();
    }
}


7.2.2 服务端

  • 构建我是服务端
  • 阻塞式监听
  • IO操作接收客户端数据
  • 处理数据
  • IO操作将结果响应给客户端
  • 关闭
public class Class006_LoginTwoWayServer {
    public static void main(String[] args) throws IOException {
        System.out.println("----我是服务端---------");
        //1.构建我是服务端  ServerSocket
        ServerSocket server = new ServerSocket(8989);
        //2.阻塞式监听 Socket accept()
        Socket client = server.accept();
        System.out.println("----一个客户端连接成功---------");
        //3.IO操作收客户端数据
        DataInputStream is = new DataInputStream(client.getInputStream());
        String str = is.readUTF();  //username=zhangsan&password=1234    //laopei     1234

        //4.处理数据
        String uname = "";
        String upwd = "";
        String[] arr = str.split("&");
        for(String s:arr){
            String[] arr2 = s.split("=");
            if("username".equals(arr2[0])){
                uname = arr2[1];
            }else if("password".equals(arr2[0])){
                upwd = arr2[1];
            }
        }
        //5.IO操作将结果响应给客户端
        DataOutputStream os = new DataOutputStream(client.getOutputStream());
        if("laopei".equals(uname) && "1234".equals(upwd)){
            os.writeUTF("登录成功");
        }else{
            os.writeUTF("登录失败");
        }

        os.flush();

        //4.关闭
        os.close();
        is.close();
        client.close();
        server.close();
    }
}

7.3 多用户登录服务器端

7.3.1 循环实现

  • 通过循环实现,可以实现允许多个客户端访问,可以对多个客户端响应
  • 但是排序访问
public class Class007_MulLoginTwoWayServer {
    public static void main(String[] args) throws IOException {
        System.out.println("----我是服务端---------");
        //1.构建我是服务端  ServerSocket
        ServerSocket server = new ServerSocket(8989);
        //2.阻塞式监听 Socket accept()
        boolean flag = true;
        while(flag){
            Socket client = server.accept();
            System.out.println("----一个客户端连接成功---------");
            //3.IO操作收客户端数据
            DataInputStream is = new DataInputStream(client.getInputStream());
            String str = is.readUTF();  //username=zhangsan&password=1234    //laopei     1234

            //4.处理数据
            String uname = "";
            String upwd = "";
            String[] arr = str.split("&");
            for(String s:arr){
                String[] arr2 = s.split("=");
                if("username".equals(arr2[0])){
                    uname = arr2[1];
                }else if("password".equals(arr2[0])){
                    upwd = arr2[1];
                }
            }
            //5.IO操作将结果响应给客户端
            DataOutputStream os = new DataOutputStream(client.getOutputStream());
            if("laopei".equals(uname) && "1234".equals(upwd)){
                os.writeUTF("登录成功");
            }else{
                os.writeUTF("登录失败");
            }

            os.flush();

            //4.关闭
            os.close();
            is.close();
            client.close();
        }
        server.close();
    }
}

7.3.2 通过多线程实现

public class Class008_MulLoginTwoWayServer {
    public static void main(String[] args) throws IOException {
        System.out.println("----我是服务端---------");
        //1.构建我是服务端  ServerSocket
        ServerSocket server = new ServerSocket(8989);
        //2.阻塞式监听 Socket accept()
        boolean flag = true;
        while(flag){
            Socket client = server.accept();
            System.out.println("----一个客户端连接成功---------");

            //开启线程为客户端服务
            new Thread(new Channel(client)).start();
        }
        server.close();
    }

    static class Channel implements Runnable{
        private Socket client = null;
        private DataInputStream is = null;
        private DataOutputStream os = null;

        public Channel(Socket client) {
            this.client = client;
            try {
                is = new DataInputStream(client.getInputStream());
                os = new DataOutputStream(client.getOutputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //读入
        public String read(){
            String str = "";
            try {
                str = is.readUTF();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        //写出
        public void write(String msg){
            try {
                os.writeUTF(msg);
                os.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //关闭
        public void close(){
            if(os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(client!=null){
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void run() {
            //3.IO操作收客户端数据
            String str = read();

            //4.处理数据
            String uname = "";
            String upwd = "";
            String[] arr = str.split("&");
            for(String s:arr){
                String[] arr2 = s.split("=");
                if("username".equals(arr2[0])){
                    uname = arr2[1];
                }else if("password".equals(arr2[0])){
                    upwd = arr2[1];
                }
            }
            //5.IO操作将结果响应给客户端

            if("laopei".equals(uname) && "1234".equals(upwd)){
                write("登录成功");
            }else{
                write("登录失败");
            }

            //4.关闭
            close();
        }
    }
}

你可能感兴趣的:(JavaSE,java)