Java网络编程快速入门【狂神篇】

1、网络编程的目的

无线电台。。。。传播交流信息、数据交换、通信

想要达到这个效果需要什么:

  • 如何准确的定位网络上的一台主机 ip地址 端口,定位到这个计算机上的某个资源
  • 找到了这个主机,如何传输数据

Javaweb: 网页编程 B/s

网络编程:TCP/IP C/S

2、网络通信的要素

如何实现网络的通信?

通信双方地址:

  • IP

  • 端口号

  • 192.168.16.124::5900

  • 规则:网络通信的协议

    TCP/IP

    小结:

    1. 网络编程中有两个主要的问题
      • 如何准确的定位到网络上的一台或多台主机
      • 找到主机之后如何进行通信
  1. 网络编程中高端要素
    • IP和端口号 IP
    • 网络通信协议 udp tcp
  2. 万物皆对象

3、ip

ip地址:inteAddress 查看本地cmd ipconfig

  • 唯一定位一台网络上计算机
  • 127.0.0.1:本机localhost
  • ip地址的分类
    • ipv4/Ipv6
      • ipv4 127.0.0.1 4个字节组成。 0~255 42亿个
      • ipv6 fe80::60f8:dddd:6bea:17a7%5 ,128位。8个无符号整数!
try {
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost);
        InetAddress[] inetAddress1 = InetAddress.getAllByName("127.0.0.1");
        System.out.println(inetAddress1);
        System.out.println(InetAddress.getByName("localhost"));
    } catch (UnknownHostException e) {
        e.printStackTrace();
    }
}

4、端口

Java网络编程快速入门【狂神篇】_第1张图片

netstat -ano #查看所有的端口
netstat -ano|findstr"5900" #查看指定的端口
taskList|findstr "8696" #查看指定端口的进程
ctrl+shift+Esc     
public static void main(String[] args) {
        InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 8080);
        InetSocketAddress localhost = new InetSocketAddress("localhost", 8080);
        System.out.println(inetSocketAddress);
        System.out.println(localhost);
    }
}

5、通信协议

网络通信协议:速率,传输码率,代码结构,传输控制…

TCP/IP协议簇:实际上是一组协议

重要:

  • TCP:用户传输协议
  • UDP:用户数据报协议

出名的协议:

  • TCP:
  • IP:网络互连协议

Java网络编程快速入门【狂神篇】_第2张图片

Java网络编程快速入门【狂神篇】_第3张图片

6、TCP

Java网络编程快速入门【狂神篇】_第4张图片

6.1、模拟客户端发送消息,服务端接收消息

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

/**
 * @author ajun
 * Date 2021/6/29
 * @version 1.0
 * 模拟客户端发送消息
 */
public class TCPClient {
    public static void main(String[] args) throws IOException {

        //socket连接
        Socket socket = null;
        //输出流
        OutputStream os = null;

        try{
            //服务器地址
            InetAddress host = InetAddress.getByName("127.0.0.1");
            //服务器端口
            int port = 9999;
            //创建socket连接
            socket = new Socket(host, port);
            //获取输出流
            os = socket.getOutputStream();
            //发送消息
            os.write("Hi,Ajun!".getBytes(StandardCharsets.UTF_8));
        }finally {
            //关闭输出流
            if(os!=null){
                os.close();
            }
            //关闭连接
            if(socket!=null){
                socket.close();
            }
        }
    }
}
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author ajun
 * Date 2021/6/29
 * @version 1.0
 * 模拟服务端接收消息
 */
public class TCPService {
    public static void main(String[] args) {
        //服务
        ServerSocket serverSocket = null;
        //连接
        Socket socket = null;
        //输入流
        InputStream is = null;
        //管道流
        ByteArrayOutputStream baos = null;

        try {
            while (true) {
                //创建服务
                serverSocket = new ServerSocket(9999);
                //等待客户端连接
                socket = serverSocket.accept();//阻塞式监听,会一直等待客户端连接

                //获取输入流
                is = socket.getInputStream();

                //建立管道流,接收消息
                baos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                //读取消息
                //int read(byte[] b):读取若干字节并填充到byte[]数组,返回读取的字节数
                while ((len = is.read(buffer)) != -1) {
                    //把 buffer 中的数据从 0 到 len,写入 baos
                    baos.write(buffer, 0, len);
                }

                System.out.println("收到!" + baos.toString());
            }

        }catch (IOException e){
        }finally {
            try{
                //关闭管道流
                if (baos != null) {
                    baos.close();
                }
                //关闭输入流
                if (is != null) {
                    is.close();
                }
                //关闭连接
                if (socket != null) {
                    socket.close();
                }
                //关闭服务
                if (serverSocket != null) {
                    serverSocket.close();
                }
            }catch (IOException e){
            }
        }
    }
}

6.2、文件上传

package com.ajun;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * @author ajun
 * Date 2021/6/29
 * @version 1.0
 * 模拟文件上传客户端
 */
public class TCPFileUploadClient {
    public static void main(String[] args) throws Exception {
        //创建连接
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9900);
        //获取输出流
        OutputStream outputStream = socket.getOutputStream();
        //读取文件
        FileInputStream inputStream = new FileInputStream("IMG_20200809_090035.jpg");
        //写入文件
        byte[] buffer = new byte[1024];
        int len;
        while((len=inputStream.read(buffer))!=-1){
            outputStream.write(buffer,0,len);
        }

        //上传完毕:关闭连接
        socket.shutdownOutput();

        //确定服务端接收完毕,然后再关闭连接
        InputStream inputStream1 = socket.getInputStream();//接收服务端反馈信息
        ByteArrayOutputStream os2 = new ByteArrayOutputStream();//把接收到的信息输出
        byte[] buffer2 = new byte[1024];
        int len2;
        while ((len2 = inputStream1.read(buffer2))!=-1){
            os2.write(buffer2,0,len2);
        }
        System.out.println(os2.toString());
        //read是阻塞的,执行完之后,后面的代码才可以执行

        //关闭
        inputStream1.close();
        os2.close();
        inputStream.close();
        outputStream.close();
        socket.close();

    }
}
package com.ajun;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

/**
 * @author ajun
 * Date 2021/6/29
 * @version 1.0
 * 模拟文件接收服务端
 */
@SuppressWarnings({"all"})
public class TCPFileUploadService {
    public static void main(String[] args) throws IOException {
        //创建服务
        ServerSocket serverSocket = new ServerSocket(9900);
        //监听连接
        Socket socket = serverSocket.accept();
        //获取输入流
        InputStream inputStream = socket.getInputStream();
        
        //文件输出
        FileOutputStream fos = new FileOutputStream("service.jpg");
        byte[] buffer = new byte[1024];
        int len;
        while((len = inputStream.read(buffer))!=-1){
            fos.write(buffer,0,len);
        }

        //通知客户端接收完毕
        OutputStream os = socket.getOutputStream();
        os.write("接收完毕".getBytes(StandardCharsets.UTF_8));
        //write是阻塞的,执行完之后,后面的代码才可以执行

        //关闭
        os.close();
        fos.close();
        inputStream.close();
        socket.close();
        serverSocket.close();
    }
}

7、UDP

不需要连接,有地址和端口即可

7.1、发送消息

package com.ajun;

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

/**
 * @author ajun
 * Date 2021/6/30
 * @version 1.0
 * 客户端发送消息
 */
public class UDPClient {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = null;

        try{
            //建立socket
            socket = new DatagramSocket();

            //建立要发送的数据包
            String msg = "Hello world!";
            byte[] buffer = msg.getBytes();
            InetAddress host = InetAddress.getByName("localhost");
            int port = 9999;
            DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length,host,port);

            //发送
            socket.send(packet);
        }finally {
            //关闭连接
            socket.close();
        }
    }
}
package com.ajun;

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

/**
 * @author ajun
 * Date 2021/6/30
 * @version 1.0
 * 服务端接收消息
 */
public class UDPService {
    public static void main(String[] args) throws IOException {

        DatagramSocket socket = null;

        try{
            //开放端口
            socket = new DatagramSocket(9999);

            //准备接收数据的容器
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);

            //接收
            socket.receive(packet);

            System.out.println("接收到的数据:"+new String(packet.getData(),0,packet.getLength()));
        }finally {
            //关闭
            socket.close();
        }
    }
}

7.2、循环发送

键盘自定义输入

循环发送

package com.ajun;

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

/**
 * @author ajun
 * Date 2021/6/30
 * @version 1.0
 * 发送
 */
public class UDPSender {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = null;
        BufferedReader reader = null;
        try{
            //建立连接
            socket = new DatagramSocket(9000);//本机端口
            //准备数据:控制台输入
            reader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("请输入要发送的消息...[注:bye 为退出]");

            //循环发送
            while (true){
                String data = reader.readLine();
                byte[] datas = data.getBytes();
                InetAddress host = InetAddress.getByName("localhost");
                int port = 8000;//接收方端口
                DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, host, port);

                //发送
                socket.send(packet);

                if(data.equals("bye")){
                    break;
                }
            }


        }finally {
            //关闭
            reader.close();
            socket.close();
        }

    }
}
package com.ajun.com.ajun;

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

/**
 * @author ajun
 * Date 2021/6/30
 * @version 1.0
 * 接收
 */
public class UDPService {
    public static void main(String[] args) throws IOException {

        DatagramSocket socket = null;

        try{
            //开启服务,监听连接
            socket = new DatagramSocket(8000);

            //循环接收
            while (true){
                //准备接收
                byte[] buffer = new byte[1024];
                DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
                //接收
                socket.receive(packet);//阻塞式

                byte[] serviceData = packet.getData();
                String sd = new String(serviceData, 0, packet.getLength());
                System.out.println(sd);

                if(sd.equals("bye")){
                    break;
                }
            }


        }finally {
            //关闭
            socket.close();
        }
    }
}

7.3、聊天

只有双方都输入 bye 时,进程才会结束

一方输入 bye 时,只有这一方断开,另一方还在连接中

  • 发送器
package com.ajun;

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

/**
 * @author ajun
 * Date 2021/6/30
 * @version 1.0
 * 发送消息
 */
public class TalkSend implements Runnable {
    private DatagramSocket socket = null;//连接
    private BufferedReader reader = null;//输入流

    private int fromPort;//发送方端口
    private int toPort;//接收方端口
    private String toHost;//接收主机
    private InetAddress host;

    //构造器
    public TalkSend(int fromPort, int toPort, String toHost) {
        this.fromPort = fromPort;
        this.toPort = toPort;
        this.toHost = toHost;
        try {
            host = InetAddress.getByName(toHost);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {

        try {
            //建立连接
            socket = new DatagramSocket(fromPort);//本机端口
            //准备数据:控制台输入
            reader = new BufferedReader(new InputStreamReader(System.in));
            //System.out.println("我是 " + Thread.currentThread().getName());
            System.out.println("发送消息...[注:bye 为退出]");

            while (true) {
                String data = reader.readLine();
                byte[] datas = data.getBytes();
                DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, host, toPort);

                //发送
                socket.send(packet);

                if (data.equals("bye")) {
                    break;
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭
            if(reader!=null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if(socket!=null){
                socket.close();
            }
        }

    }
}
  • 接收器
package com.ajun;

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

/**
 * @author ajun
 * Date 2021/6/30
 * @version 1.0
 * 接收消息
 */
public class TalkReceive implements Runnable {
    private DatagramSocket socket = null;
    private int receivePort;//接收端口
    private String sender;//发送方

    public TalkReceive(int receivePort, String sender) {
        this.receivePort = receivePort;
        this.sender = sender;
    }

    @Override
    public void run() {

        try {
            //开启服务,监听连接
            socket = new DatagramSocket(receivePort);

            while (true) {
                //准备接收
                byte[] buffer = new byte[1024];
                DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
                //接收
                socket.receive(packet);//阻塞式

                byte[] serviceData = packet.getData();
                String sd = new String(serviceData, 0, packet.getLength());
                System.out.println("[" + sender + "] " + sd);

                if (sd.equals("bye")) {
                    break;
                }
            }

        } catch (IOException e) {
        }finally {
            //关闭
            if (socket != null) {
                socket.close();
            }
        }
    }
}
  • 聊天一方
package com.ajun;

/**
 * @author ajun
 * Date 2021/6/30
 * @version 1.0
 * 聊天一方:小王
 */
public class Person1 {
    public static void main(String[] args) {
        //小王:发送端口9600,接收端口9700
        //小花:发送端口9800,接收端口9900
        TalkSend send = new TalkSend(9600, 9900, "localhost");//小王给小花发送消息
        TalkReceive receive = new TalkReceive(9700,"小花");//小王接收小花消息

        new Thread(send).start();
        new Thread(receive).start();
    }
}
  • 聊天另一方
package com.ajun;

/**
 * @author ajun
 * Date 2021/6/30
 * @version 1.0
 * 聊天另一方:小花
 */
public class Person2 {
    public static void main(String[] args) {
        //小王:发送端口9600,接收端口9700
        //小花:发送端口9800,接收端口9900
        TalkSend send = new TalkSend(9800, 9700, "localhost");//小花给小王发送消息
        TalkReceive receive = new TalkReceive(9900,"小王");//小花接收小王的消息

        new Thread(send).start();
        new Thread(receive).start();
    }
}

8、URL

URL(Uniform Resource Locator,统一资源定位器)

  • URL由三部分组成:资源类型、存放资源的主机域名、资源文件名。

  • 也可认为由4部分组成:协议、主机、端口、路径

  • URL的一般语法格式为:

  • (带方括号[]的为可选项):

  • protocol / hostname[:port] / path / [;parameters][?query]#fragment

你可能感兴趣的:(Java,网络编程,TCP,UDP)