狂神笔记—网络编程

网络编程

1.1 概述

​ 1.1.1 连接的两种方式(数据以包的形式进行传输,所以会存在丢包现象,也就是数据可能有损失):

​ 1.打电话 - 连接 - 接了 - 通话 TCP

​ 2.发短信 - 发完了 - 接收到/没接收到 UDP

​ 1.1.2计算机网络:

​ 计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统网络管理软件及==网络通信协议==的管理和协调下,==实现资源共享==和信息传递的计算机系统。

​ 1.1.3网络编程的目的:

​ 实现传播信息交流,数据交换,通信。

​ 1.1.4如何达到这种效果:

​ 1.如何准确的定位网络是的一台主机 局域网:端口号,定位到这个计算机上的某个资源

​ 2.找到这台主机该如何传输数据?

1.2 网络通信的要素

如何实现网络通信?
​ 通信两方的地址:
​ 1.ip 和端口号:IP (将两者用:连起来即可)
​ 2.网络通信协议:udp、te 规则:网络通信的协议
都用new来new出想要的对象即可

1.3 IP

ip地址:InetAddress

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

  • 127.0.0.1:本机localhost

  • ip地址分类:

    • IPV4/IPV6:

      • IPV4:127.0.0.1,由4个字节组成(用.隔开),每个字节可以是0~255
      • IPV6:128位,由0123456789abcdef(十六进制)组成,4个整数为一组,用5个:分隔成6组(eg: 2002:abbb:525a:1aaa:bddd:56ab)
    • 公网(互联网)- 私网(局域网)

      • ABCD类地址
      • 192.168.xx.xx,专门给组织内部使用
  • 域名:记忆IP问题

    • IP:www.xxx.com

IP类的代码实现:InetAddress类

import java.net.InetAddress;
import java.net.UnknownHostException;

//测试IP
public class TestIP {
    public static void main(String[] args) {
        try {
            //因为没有构造方法,所以不能通过new来生成对象,但是可以通过类名来调用类的静态方法
            //查询本机地址
            InetAddress inetAddress1 = InetAddress.getByName("localhost");
            System.out.println(inetAddress1);
            InetAddress inetAddress2 = InetAddress.getLocalHost();
            System.out.println(inetAddress2);

            //查询网站ip
            InetAddress inetAddress3 = InetAddress.getByName("www.baidu.com");
            System.out.println(inetAddress3);//结果:www.baidu.com/183.232.231.174

            //常用方法
            System.out.println(inetAddress3.getHostAddress());//ip
            //结果:183.232.231.174
            System.out.println(inetAddress3.getCanonicalHostName());//规范的名字
            //结果:183.232.231.174
            System.out.println(inetAddress3.getHostName());//返回域名,或者自己电脑的名称
            //结果:www.baidu.com

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

1.4 端口Port

端口表示计算机上的一个程序进程

  • 不同的进程有不同的端口号,用来区分软件
  • 被规定0-65535(代表可以跑65535个程序)
  • TCP,UDP:65535 * 2,单个协议下,端口号不能冲突,如tcp用80,那udp也能用 80,因为是两个不同的协议。
  • 端口分类
    - 公有端口 0~1023
    - HTTP:80
    - HTTPS:443
    - FTP:21
    - Telent:23
    • 程序注册端口:1024~49151,分配用户或者程序
      - Tomcat:8080
      - MySOL:3306
      - Oracle:1521
      - 动态、私有:49152~65535
      - DOC命令:
      netatat -ano //查看所有端口
      netstat -ano|findstr"5900" //查看指定端口
      tasklist|findstr"8696" //查看指定端口进程

端口的代码实现:InetSocketAddress类

import java.net.InetSocketAddress;

public class TestInetSocketAddress {

    public static void main(String[] args) {
        //有构造方法,所以可以创造对象
        InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 8080);
        System.out.println(inetSocketAddress);//输出ip加端口:/127.0.0.1:8080

        System.out.println(inetSocketAddress.getAddress());//输出:/127.0.0.1
        System.out.println(inetSocketAddress.getHostName());//输出:127.0.0.1,获取地址
        System.out.println(inetSocketAddress.getPort());//输出:8080,获取端口
    }
}

1.5通信协议

​ 协议:约定,就好比我们现在对话用的是普通话

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

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

​ 重要:

	- TCP:用户传输协议
	- UDP:用户数据协议

​ 出了名的协议:

- TCP:传输控制协议
- IP:网络互连协议

TCP 和 UDP对比

TCP:类比打电话

三次握手(模拟场景):
a:可以和你连接吗
b: 真的想和我连接
a: 对的
//然后才建立连接

四次挥手(模拟场景):
a:我要走了
b:你要走?
b:你真的要走了?
a:对,我真的要走了
//然后才断开连接
  • 客户端、服务端
  • 传输完成,释放连接,效率低

UDP:类比发信息

-  不连接,不稳定
-  客户端、服务端:没有明确的界限
-  不管准备好没,都可以发给你
-  DDOS:(饱和攻击),类似于短信轰炸,堵住传输路径

1.6 TCP

客户端

  1. 连接服务器Socket
  2. 发送信息
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;

//客户端
public class TcpClientDemo01 {
    public static void main(String[] args) {

        Socket socket = null;
        OutputStream os = null;
        try {
            //1.要知道服务器地址
            InetAddress serverIP = InetAddress.getByName("127.0.0.1");
            //端口号
            int port = 9999;

            //2.创建一个socket连接
                socket = new Socket(serverIP,port);//客户端的连接器
                //3.发送信息io流
                os = socket.getOutputStream();//输出流

                os.write("你好,我是小爱".getBytes());

            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                //关闭连接,要按照顺序依次关闭
                if (os != null){
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                if(socket != null) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

    }
}

服务器

  1. 建立服务端口ServerSocket
  2. 等待用户链接accept
  3. 接收用到的信息
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

//服务端
public class TcpServerDemo01 {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;

        try {
            //1、我得有一个地址,创建出来的地址为localhost:999
             serverSocket = new ServerSocket(9999);//服务端的连接器
            //2.等待客户端连接
             socket = serverSocket.accept();
            //3.读取客户端的消息
             is = socket.getInputStream();

            /*byte[] buffer = new byte[1024];
            int len;
            while((len = is.read(buffer)) != -1){
                String msg = new String(buffer,0,len);//从buffer里面拼,下标从0-len
                System.out.println(msg);
            }*/
            //或者用管道流
            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());//直接打印出结果


        } catch (IOException e) {
            e.printStackTrace();
        }finally {

            //关闭资源,一个一个关
            if(baos != null){
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
                if(is != null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                if(socket != null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                if(serverSocket!= null){
                    try {
                        serverSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

        }
    }
}

文件上传

1.以Socket类对象来作为客户端和服务器端的连接

2.先运行服务端,再让客户端运行,从而连接上去

3.文件传输或者信息的传输都要用到io中的管道流

4.当运行完毕后,包目录下就会有所传输的文件

客户端

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
//客户端
public class TcpClientDemo02 {
    public static void main(String[] args) throws Exception {
        //1.创建一个socket连接
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
        //2.创建一个输出流
        OutputStream os = socket.getOutputStream();
        //3.文件流,读取文件
        FileInputStream fis = new FileInputStream(new File("D:\\Idea\\ideaiu-2019.3.3\\workspace02\\src\\网络编程\\TCP\\1.jpg"));//文件路径写清楚
        //4.写出文件
        byte[] buffer = new byte[1024];
        int len;
        while((len = fis.read(buffer)) != -1){
            os.write(buffer,0,len);//写出buffer中0-len下标的元素
        }

        //通知服务器我已经结束了
        socket.shutdownOutput();//我已经传输完毕

        //确定服务器接收完毕,才能断开连接
        InputStream inputStream = socket.getInputStream();
        //String byte[],通过字符的管道流来接收服务端传输的提示信息
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer2 = new byte[1024];
        int len2;
        while((len = inputStream.read(buffer)) != -1){
            baos.write(buffer,0,len);
        }
        System.out.println(baos.toString());

        //5.关闭资源
        baos.close();
        inputStream.close();
        fis.close();
        os.close();
        socket.close();

        //Process finished with exit code 0
    }
}

服务端

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务端
public class TcpServerDemo02 {
    public static void main(String[] args) throws Exception {
        //1.创建服务
        ServerSocket serverSocket = new ServerSocket(9000);
        //2.监听客户端的连接
        Socket socket = serverSocket.accept();//阻塞式监听,会一直等待客户端连接,类比scanner.next()
        //3.获取输入流
        InputStream is = socket.getInputStream();

        //4.文件输入,用文件的管道流
        FileOutputStream fos = new FileOutputStream("recieve.jpg");
        byte[] buffer = new byte[1024];
        int len;
        while((len = is.read(buffer)) != -1){
            fos.write(buffer,0,len);
        }

        //通知客户端我接收完毕了
        OutputStream os = socket.getOutputStream();
        os.write("我接收完了".getBytes());
        //关闭资源
        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }

}

Tomcat

服务端

  • 自定义服务端 S
  • Tomcat服务器S: java后台开发

客户端

  • 自定义客户端 C
  • 浏览器 B

1.7 UDP

发送信息

服务端:

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
//服务端
public class UdpServerDemo01 {
    public static void main(String[] args) throws Exception {
        //开放端口
        DatagramSocket socket = new DatagramSocket(9000);
        //接收数据包
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);

        socket.receive(packet);//阻塞接收

        System.out.println(packet.getAddress().getHostAddress());//输出地址
        System.out.println(new String(packet.getData(),0,packet.getLength()));//输出传输内容

        //关闭资源
        socket.close();
    }
}

客户端:不需要与服务端建立连接也可以发送

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
//客户端
public class UdpClientDemo01 {
    public static void main(String[] args) throws Exception {
        //1.创建一个Socket连接
        DatagramSocket socket = new DatagramSocket();
        //2.建个包
        String msg = "你好,服务器";

        //发送给谁
        InetAddress localhost = InetAddress.getByName("localhost");
        int port = 9000;
        //参数分别为:数据(要转换为字符数组),数据长度,要发送给谁(地址和端口号)
        DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);

        //3.发送包
        socket.send(packet);

        //4.关闭资源
        socket.close();
    }
}

聊天(单向聊天)

发送方:

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

public class UdpSenderDemo01 {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket(8888);

        //准备数据作为参数传进datagramPacket,所以要从控制台进行读取System.in
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        while(true){
            String data = reader.readLine();
            byte[] datas = data.getBytes();
            //数据要以byte[]的形式传入
            DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666));
            //发送数据包
            socket.send(packet);
			
            //当发送bye时断开连接
            if(data.equals("bye")){
                break;
            }
        }

        //关闭资源
        socket.close();
    }
}

接收方:

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

public class UdpReceiveDemo01 {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket(6666);

        while(true) {

            //准备包接收
            byte[] container = new byte[1024];
            DatagramPacket packet = new DatagramPacket(container, 0, container.length);
            socket.receive(packet);

            //断开连接
            byte[] data = packet.getData();
            //trim不用的话会打印出很多方格
            String receivedatas = new String(data, 0, data.length).trim();
            System.out.println(receivedatas);

            if (receivedatas.equals("bye")) {
                break;//当传入的数据是bye的时候就会断开连接
            }

        }

        socket.close();//关闭资源
    }
}

聊天(互相聊天)

以老师和学生聊天为例(多线程实现):

老师和学生每人都应有一个接收端和发送端

接收信息端:

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

public class TalkReceive implements Runnable{
    DatagramSocket socket = null;
    private int port;
    private String msg;

    public TalkReceive(int port,String msg)  {

        try {
            this.port = port;
            this.msg = msg;
            socket = new DatagramSocket(port);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
    while(true) {

        try {
            //准备包接收
            byte[] container = new byte[1024];
            DatagramPacket packet = new DatagramPacket(container, 0, container.length);
            socket.receive(packet);

            //断开连接
            byte[] data = packet.getData();
            //trim不用的话会打印出很多方格
            String receivedatas = new String(data, 0, data.length).trim();
            System.out.println(msg + ":" + receivedatas);

            if (receivedatas.equals("bye")) {
                break;//当传入的数据是bye的时候就会断开连接
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
        socket.close();//关闭资源
    }


}

发送信息端:

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

public class TalkSend implements Runnable{
    DatagramSocket socket = null;
    BufferedReader reader = null;
    private int fromPort;//我自己的IP
    private String toIP;//对方的地址
    private int toPort;//对方的端口号

    public TalkSend(int fromPort, String toIP, int toPort) {
        this.fromPort = fromPort;
        this.toIP = toIP;
        this.toPort = toPort;

        try {
            socket = new DatagramSocket(fromPort);
            //准备数据作为参数传进datagramPacket,所以要从控制台进行读取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[] datas = data.getBytes();
                //数据要以byte[]的形式传入
                DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress(this.toIP,this.toPort));
                //发送数据包
                socket.send(packet);

                if(data.equals("bye")){
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        //关闭资源
        socket.close();
    }
}

然后是老师和学生的类:

老师:

public class TalkTeacher {
    public static void main(String[] args) {
        new Thread(new TalkSend(4321,"localhost",8888)).start();
        //port代表该接收器端口号是9999,接收的包为学生传输的包
        new Thread(new TalkReceive(9999,"学生")).start();
    }
}

学生:

public class TalkStu {
    public static void main(String[] args) {
        //topot代表发送到xxxx端口号
        new Thread(new TalkSend(1234,"localhost",9999)).start();
        //port代表该接收器端口号是8888,接收的包为老师传输的包
        new Thread(new TalkReceive(8888,"老师")).start();

    }
}

即可实现双方的对话:

​ 老师:

在这里插入图片描述

​ 学生:

在这里插入图片描述

URL


eg:https://www.baidu.com/

统一资源定位符:定位资源的,定位互联网上的某一个资源

DNS域名解析:将www.xxxx.com转换为xxx.x…x…xx


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

URL类的基本使用:

import java.net.MalformedURLException;
import java.net.URL;

public class URLDemo01 {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("https://blog.csdn.net/hanpiyo?type=blog");
        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());//获取查询的名字,参数
    }
}

使用URL类下载网络资源:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class UrlDown {
    public static void main(String[] args) throws Exception {

        //1.下载地址
        URL url = new URL("https://p1.music.126.net/VTZde5VdBm_u2WH0Pc9HQQ==/109951165561227373.jpg?param=130y130");
        //2.连接到这个下载地址   HTTP
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();//打开连接

        InputStream inputStream = urlConnection.getInputStream();
        FileOutputStream fos = new FileOutputStream("109951165561227373.jpg");//参数是文件名称

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

        //关闭资源
        fos.close();
        inputStream.close();
        urlConnection.disconnect();//断开连接
    }
}

下载完之后便会看到所下载好的资源:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值