网络编程及练习

定义:

在网络通信协议下,不同计算机上运行的程序进行的数据传输。计算机和计算机之间通过网络进行数据传输

可以使用在java.net包下的技术开发出常见的网络应用程序

常见的软件架构:

C/S: Client/Server 客户端/服务器 在用户本地需要下载并安装客户端程序,在远程有一个服务器端程序

优点:画面精美,用户体验好

缺点:需要开发客户端,也需要开发服务端,用户需要下载和更新的时候太麻烦

B/S:Browser/Server 只需要一个浏览器,用户通过不同的网址,客户访问不同的服务器

优点:不需要开发客户端,只需要页面+服务端;用户不需要下载,打开浏览器就能使用;

缺点:如果应用过大,用户体验会受影响

三要素:IP 端口号 协议

IP:

设备在网络中的地址,是唯一的标识

定义:

全称:Internet Protocol,是互联网协议地址,也称IP地址,是分配给上网设备的数字标签,通俗理解:上网设备在网络中的地址,是唯一的

分类:

IPv4 IPv6

IPv4:

全称:Internet Protocol version 4,互联网通信协议第四版

采用32位地址长度,分成4组 2^32方个ip

点分十进制表示法:每8位表示为一个十进制数,中间用.隔开

IPv6:

全称:Internet Protocol version 6,互联网通信协议第六版

采用128位地址长度,分成8组

冒分十六进制表示法:将上面每一组用16进制表示,可以省略前面的0

特殊情况:如果计算出的16进制表示形式中间有多个连续的0,可以用::表示

地址分类形式:

公网地址(万维网使用)和私有地址(局域网使用)

192.168.开头的就是私有地址,范围为:192.168.0.0 -- 192.168.255.255,专门为组织机构内部使用,以此节省IP

特殊IP地址:127.0.0.1,也可以是localhost:是回送地址也称本地回环地址,也称本机IP,永远只会寻找当前所在本机

图来自黑马程序员网课

端口号:

应用程序在设备中唯一的标识

由两个字节表示的整数,取值范围:0~65535,其中0~1023之间的端口号用于一些知名的网络服务或者应用,自己使用1024以上的端口号就可以了

注意:一个端口号只能被一个应用程序使用

协议:

数据在网络中传输的规则,常见的协议有UDP,TCP,http,https,ftp

OSI参考模型:世界互联协议标准,全球通信规范,

TCP/IP参考模型(TCP/IP协议):事实上的国际标准

图来自黑马程序员网课

TCP协议:传输控制协议(Transmission Control Protocol),它是面向连接通信协议,速度慢,没有大小限制,数据安全

TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,通信之前要保证连接已经建立,通过Socket产生IO流来进行网络通信

图来自黑马程序员网课

客户端代码:

java 复制代码
package com.lazyGirl.netdemo.tcpdemo;

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

public class Client {
    public static void main(String[] args) throws IOException {

        //在创建该对象的同时会连接服务端,如果连不上,代码会报错
        Socket socket = new Socket("127.0.0.1",10086);

        //可以从连接通道中获取输出流
        OutputStream os = socket.getOutputStream();
        os.write("你好".getBytes());

        os.close();
        socket.close();
    }
}

服务端代码:

java 复制代码
package com.lazyGirl.netdemo.tcpdemo;

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

public class Server {
    public static void main(String[] args) throws IOException {

        ServerSocket serverSocket = new ServerSocket(10086);

        Socket socket = serverSocket.accept();

//        InputStream inputStream = socket.getInputStream();
//        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
//        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);


        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        int b;
        while ((b = br.read()) != -1) {
            System.out.print((char) b);
        }

        socket.close();
        serverSocket.close();

    }
}

输出:

UDP协议:用户数据报协议(User Datagram Protocol),它是面向无连接通信协议,速度快,有大小限制,一次最多发送64K,数据不安全,易丢失数据

图来自黑马程序员网课

UDP的三种通信方式:

单播:

组播: 组播地址:224.0.0.0 ~ 239.255.255.255 其中224.0.0.0 ~ 224.0.0.255为预留的组播地址

接收端1:

java 复制代码
package com.lazyGirl.netdemo.udpdemo;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

public class ReceiveMessageDemo {
    public static void main(String[] args) throws IOException {

        MulticastSocket ms = new MulticastSocket(10086);

        InetAddress group = InetAddress.getByName("224.0.0.1");
        ms.joinGroup(group);
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf, buf.length);
        ms.receive(dp);

        byte[] data = dp.getData();
        int len = data.length;
        String ip = dp.getAddress().getHostAddress();
        String name = dp.getAddress().getHostName();

        System.out.println("ip: " + ip + " name: " + name + " len: " + len + " data: " + new String(data));

        ms.close();

    }
}

发送端:

java 复制代码
package com.lazyGirl.netdemo.udpdemo;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

public class SendMessageDemo {
    public static void main(String[] args) throws IOException {

        MulticastSocket ms = new MulticastSocket();

        String s = "hello";
        byte[] buf = s.getBytes();
        InetAddress addr = InetAddress.getByName("224.0.0.1");
        int port = 10086;

        DatagramPacket dp = new DatagramPacket(buf, buf.length, addr, port);
        ms.send(dp);
        ms.close();


    }
}

输出:

两个接收端都接收到了消息

图来自黑马程序员网课

广播:255.255.255.255

将上面的地址改成255.255.255.255即实现该局域网内所有主机都收到消息

常见的CMD命令:

ipconfig: 查看本机ip地址

ping: 检查网络是否连通

InetAddress:

接收端:

java 复制代码
package com.lazyGirl.netdemo;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

public class ReceiveMessageDemo {
    public static void main(String[] args) throws IOException {


        //必须指定端口,且跟发送端口一致
        DatagramSocket socket = new DatagramSocket(10086);


        byte[] buf = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);
        socket.receive(packet);

        byte[] data = packet.getData();
        int len = packet.getLength();
        InetAddress address = packet.getAddress();
        int port = packet.getPort();

        System.out.println("data " + new String(data,0,data.length));
        System.out.println("address " + address.getHostAddress());
    }
}

receive函数会阻塞

发送端:

java 复制代码
package com.lazyGirl.netdemo;

import java.io.IOException;
import java.net.*;

public class SendMessageDemo {
    public static void main(String[] args) throws IOException {

        DatagramSocket socket = new DatagramSocket();

        String str = "hello";
        byte[] buf = str.getBytes();

        InetAddress address = InetAddress.getByName("192.168.1.111");

        int port = 10086;
        DatagramPacket packet = new DatagramPacket(buf, buf.length, address, port);

        socket.send(packet);

        socket.close();
    }
}

输出:

聊天室:

发送端:

java 复制代码
package com.lazyGirl.netdemo.netcase1;

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class SendMessageDemo {
    public static void main(String[] args) throws IOException {

        DatagramSocket socket = new DatagramSocket();

        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("Enter your message");
            String message = scanner.nextLine();

            if ("886".equals(message)) {
                break;
            }

            byte[] data = message.getBytes();

            InetAddress address = InetAddress.getByName("lazyGril");

            int port = 10086;

            DatagramPacket packet = new DatagramPacket(data, data.length, address, port);

//            System.out.println("Sending Message");

            socket.send(packet);
        }

        socket.close();

    }
}

接收端:

java 复制代码
package com.lazyGirl.netdemo.netcase1;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class ReceiveMessageDemo {
    public static void main(String[] args) throws IOException {


        DatagramSocket socket = new DatagramSocket(10086);

        byte[] buf = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);

        while (true) {
            socket.receive(packet);
            byte[] data = packet.getData();
            int len = packet.getLength();
            int port = packet.getPort();
            String ip = packet.getAddress().getHostAddress();
            String name = packet.getAddress().getHostName();

            System.out.println("ip: " + ip + " name: " + name + " port: " + port + " len: " + len + " data: " + new String(data));
        }

    }
}

输出:

练习:

case1:

客户端:发送一条数据,接收服务端反馈的消息并打印

服务器:接收数据并打印,再给客户端反馈消息

线程池版:

客户端:

java 复制代码
package com.lazyGirl.netdemo.test3;

import java.io.*;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {

        Socket socket = new Socket("127.0.0.1",10086);
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        byte[] buf = new byte[1024];
        int len;
        while ((len = bis.read(buf)) != -1) {
            bos.write(buf, 0, len);
        }
        socket.shutdownOutput();

        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String str = br.readLine();
        System.out.println(str);

        socket.close();
    }
}

服务端:

java 复制代码
package com.lazyGirl.netdemo.test3;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
import java.util.concurrent.*;

public class Server {
    public static void main(String[] args) throws IOException {

        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                3,
                16,
                60,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        ServerSocket serverSocket = new ServerSocket(10086);
        while (true) {
            Socket socket = serverSocket.accept();
            pool.submit(new MyRunnable(socket));

        }
    }
}
java 复制代码
package com.lazyGirl.netdemo.test3;

import java.io.*;
import java.net.Socket;
import java.util.UUID;

public class MyRunnable implements Runnable {

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

    @Override
    public void run() {
        try{
            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
            String name = UUID.randomUUID().toString().toString().replaceAll("-", "");
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(name + ".txt"));
            int len;
            byte[] buf = new byte[1024];
            while ((len = bis.read(buf)) != -1) {
                bos.write(buf, 0, len);
            }

            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            bw.write("上传成功");
            bw.newLine();
            bw.flush();
            bw.close();
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

输出:

相关推荐
炫酷的伊莉娜8 分钟前
【计算机网络】数据链路层(作业)
网络·计算机网络·数据链路层
xy189908 分钟前
http 状态码主要有哪些?【面试】
网络·网络协议·http
来世做春风嘛20 分钟前
第二十一章 网络编程
服务器·网络·php
Tony11541 小时前
华为路由器静态路由配置(eNSP模拟实验)
网络·华为·智能路由器
斐夷所非1 小时前
RIP 路由 3 个定时器的工作流程和 4 种防环方法
网络
速盾cdn3 小时前
速盾:cdn发展历程
服务器·网络·安全
阿龍17873 小时前
Qt中udp指令,大小端,帧头帧尾实际示例
网络·c++·qt·网络协议·udp
爱喝矿泉水的猛男4 小时前
无线传感器网络(物联网通信技术)期末考试2024年真题
网络·arm开发·物联网·wsn·物联网通信技术
梦中北山4 小时前
JWT安全分析
开发语言·网络·安全·web安全·php
hgdlip4 小时前
路由器的ip地址与网关的区别是什么
网络·网关·tcp/ip·智能路由器