Java网络编程详细笔记(附各类应用代码)

1、概述

想要达到网络通讯效果需要什么:

  1. 如何准确定位网上的一台主机,192.168.16.124: 端口,定位到这个计算机的某个资源
  2. 找到了这个主机,如何传播数据

JavaWeb与网络编程的区别

JavaWeb:网页编程 B/C. (Brower/Server)

网络编程:TCP/IP 使用 C/S 架构 (Client/Server)

2、IP

IP地址在 JavaInetAddress 类中

  • 唯一定位一台网络上的计算机

  • 本机127.0.0.1: localhost.

    public static void main(String[] args) {
        try{
            //查询本机地址
            InetAddress inetAddress1= InetAddress.getByName("127.0.0.1");
            System.out.println(inetAddress1);
    
            InetAddress inetAddress2= InetAddress.getByName("localhost");
            System.out.println(inetAddress2);
    
            InetAddress inetAddress3= InetAddress.getLocalHost();
            System.out.println(inetAddress3);
    
            //查询网络ip地址
            InetAddress inetAddress4 = InetAddress.getByName("www.baidu.com");
            System.out.println(inetAddress4);
    
        }catch (UnknownHostException e){
            e.printStackTrace();
        }
    }
    
    

3、网络通信协议

各个端间通信的标准,使得接收方和发送方对数据没有歧义,同时规定端间数据传输的速率、包/帧结构、实现传输控制等。

3.1TCP

​ TCP协议的特点是面向连接的通信协议,保证数据的安全和完整性即在传输数据前先在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”。

  • 三次握手、 四次挥手,面向连接相对稳定,

  • 客户端

    • 连接服务器Socket
    • 发送消息
  • 服务器

    • 建立服务端口ServerSocket
    • 等待用户的连接accept
    • 接受用户的消息

    客户端:

package SunSocket;

import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class Socket_01 {
    public static void main(String[] args) throws Exception {
        //要知道服务器地址
        //InetAddress.getByName()
        InetAddress sAddress=InetAddress.getByName("127.0.0.1");
        //端口号
        int port=9999;
        //创建socket连接
        Socket socket=new Socket(sAddress,port);
        //发送消息,IO流
        OutputStream stream = socket.getOutputStream();
        stream.write("我爱学网络通讯".getBytes());
        stream.write('\n');
        stream.write("我真的很爱学网络通讯".getBytes());
        stream.close();
        socket.close();
    }
}

服务端:

package SunSocket;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Socket_02 {
    public static void main(String[] args) throws Exception {
        //需要有一个地址
        ServerSocket serverSocket = new ServerSocket(9999);
        //等待客户端连接
        Socket socket=serverSocket.accept();
        //读取消息
        InputStream is=socket.getInputStream();
        //管道流
        ByteArrayOutputStream baos=new ByteArrayOutputStream();
        byte[] buffer =new byte[1024];
        int len;
        while ((len=is.read(buffer))!=-1){
            baos.write(buffer,0,len);
        }
        System.out.println(baos.toString());
        baos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}

image-20201105224504055

3.2UDP

3.2.1发送消息

​ UDP协议的特点是面向无连接的通信协议,不保证数据的完整性,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据,例如:我们的供屏软件。

发送端:

package SunSocket;

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


public class UdpSocket_01 {
    public static void main(String[] args) throws Exception {
        //建立Socket
        DatagramSocket socket=new DatagramSocket();
        //打包数据包
        String msg="我爱学UDP协议";
        new DatagramPacket(msg.getBytes(),0,msg.getBytes().length);
        //发送
        InetAddress address= InetAddress.getByName("127.0.0.1");
        int post=9090;
        DatagramPacket packet=new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,address,post);
        socket.send(packet);
        socket.close();
    }
}

接受端:

package SunSocket;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

//服务器端,等待客户端的数据包
public class UdpSocket_02 {
    public static void main(String[] args) throws Exception {
        //开放端口
        DatagramSocket socket=new DatagramSocket(9090);
        //接受数据包
        byte[] buffer=new byte[1024];
        DatagramPacket packet=new DatagramPacket(buffer,0,buffer.length);
        socket.receive(packet);//阻塞接受
        System.out.println(new String(packet.getData()));
        //关闭连接
        socket.close();
    }
}

image-20201106114708813

3.2.2循环发送消息

发送端:

package SunSocket;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

public class UdpSocket_03 {
    public static void main(String[] args) throws Exception {
        //构造数据报套接字并将其绑定到本地主机上的9999端口。
        DatagramSocket socket = new DatagramSocket(9999);
        while (true) {
            //准备数据,从控制台读取System.in
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            String data = reader.readLine();
            //准备封装发送包
            byte[] dataBytes = data.getBytes();
            //构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。
            //InetSocketAddress从IP地址和端口号创建套接字地址。 
            DatagramPacket packet = new DatagramPacket(dataBytes, 0, dataBytes.length, new InetSocketAddress("localhost", 6666));
            //发送
            socket.send(packet);
            if(data.equals("bye")){
                break;
            }
        }
        socket.close();
    }
}

接收端:

package SunSocket;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UdpSocket_04 {
    public static void main(String[] args) throws Exception {
        //构造数据报套接字并将其绑定到本地主机上的6666端口。
        DatagramSocket socket = new DatagramSocket(6666);
        while (true) {
            //准备接收包裹
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
            socket.receive(packet);//阻塞接受
            byte[] data = packet.getData();
            //此处的Length选用receivedPacket的Length,若选用data的Length,可能会变成1024,并没有进行动态生成长度
            String receiveMsg = new String(data, 0, packet.getLength());
            System.out.println(receiveMsg);
            if (receiveMsg.equals("bye")) {
                break;
            }
        }
        socket.close();
    }
}

image-20201106200149547

image-20201106200203724

3.2.3多线程实现在线咨询

发送端:

package SunSocket;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class UdpSocket_05 implements Runnable{
    DatagramSocket socket=null;
    BufferedReader reader=null;
    private int fromPost;
    private String toIp;
    private int toPost;

    public UdpSocket_05(int fromPost, String toIp, int toPost) {
        this.fromPost = fromPost;
        this.toIp = toIp;
        this.toPost = toPost;
        try{
            //构造数据报套接字并将其绑定到本地主机上的9999端口。
            socket = new DatagramSocket(this.fromPost);
            //准备数据,从控制台读取System.in
            reader = new BufferedReader(new InputStreamReader(System.in));
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
            try {
                String data = reader.readLine();
                //准备封装发送包
                byte[] dataBytes = data.getBytes();
                //构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。
                //InetSocketAddress从IP地址和端口号创建套接字地址。
                DatagramPacket packet = new DatagramPacket(dataBytes, 0, dataBytes.length, new InetSocketAddress(this.toIp,this.toPost));
                //发送
                socket.send(packet);
                if (data.equals("bye")) {
                    break;
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        socket.close();
    }
}

接收端:

package SunSocket;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UdpSocket_06 implements Runnable{
    DatagramSocket socket;
    DatagramPacket packet;
    private String name;
    private int port;

    public UdpSocket_06(int port,String name) {
        this.port = port;
        this.name=name;
        try{
            socket=new DatagramSocket(this.port);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
        try{
                //准备接收包裹
                byte[] buffer = new byte[1024];
                packet = new DatagramPacket(buffer, 0, buffer.length);
                socket.receive(packet);//阻塞接受
                byte[] data = packet.getData();
                //此处的Length选用receivedPacket的Length,若选用data的Length,可能会变成1024,并没有进行动态生成长度
                String receiveMsg = new String(data, 0, packet.getLength());
                System.out.println(name+":"+receiveMsg);
                if (receiveMsg.equals("bye")) {
                    break;
                }
        }catch (Exception e) {
            e.printStackTrace();
        }
        }
        socket.close();
    }
}


学生测试:

package SunSocket;
//测试多线程UDP1
public class UdpSocket_07 {
    public static void main(String[] args) {
        new Thread(new UdpSocket_05(7777,"127.0.0.1",8888)).start();
        new Thread(new UdpSocket_06(9999,"老师")).start();
    }
}

老师测试:

package SunSocket;
//测试UDP2
public class UdpSocket_08 {
    public static void main(String[] args) {
        new Thread(new UdpSocket_05(5555,"127.0.0.1",9999)).start();
        new Thread(new UdpSocket_06(8888,"学生")).start();
    }
}

image-20201106211611604

image-20201106211628667

1.4URL

统一资源定位符:Uniform Resource Locator

协议://ip地址:端口//项目名/资源
package SunSocket;

import java.io.FileOutputStream;
        import java.io.InputStream;
        import java.net.HttpURLConnection;
        import java.net.URL;

public class Url_01 {
    public static void main(String[] args) throws Exception {
        //1、下载资源(参数为地址)
        URL url = new URL("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png");
        System.out.println(url.getProtocol());  //协议名
        System.out.println(url.getHost());  //IP名字
        System.out.println(url.getPort());   //端口号
        System.out.println(url.getPath());   //文件
        System.out.println(url.getFile());   //文件全路径
        System.out.println(url.getQuery());   //参数

        //2、连接到这个资源 HTTP
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

        InputStream is = urlConnection.getInputStream();

        FileOutputStream fos = new FileOutputStream("D:\\Desktop\\DownLoad.png");

        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) != -1){
            fos.write(buffer,0,len);  //写出这个数据
        }

        //关闭资源
        fos.close();
        is.close();
        urlConnection.disconnect();
    }
}

image-20201106212847572

image-20201106212858196

自学习于哔哩哔哩狂神说JAVA(侵删);

作为自己的笔记,欢迎大家斧正!

posted @ 2020-11-06 21:34  -SUN-  阅读(288)  评论(0编辑  收藏  举报