2021-11-07  2021-11-07    4684 字   10 分钟

网络编程

网络编程概述

网络

计算机网络:计算机网络系统就是利用通信设备和线路将地理位置不同、功能独立的多个计算机系统互

联起来,以功能完善的网络软件实现网络中资源共享和信息传递的系统

网络三要素

1.ip地址:标识计算机,是计算机在互联网上的唯一标识地址。

2.端口号:标识计算机上的软件的。不同的软件有不同的端口号,端口号 2个字节,0~65535 一般建

议使用8000之后。

mysql 3306 tomcat 8080

3.通信协议:双方应该遵循的规则。

HTTP:超文本传输协议

FTP: 文件传输协议

TCP/IP:传输控制协议/网际协议

UDP:用户数据包协议

网络的分层架构

IP地址

IP地址(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址。标识计算机在互联网上的唯一地址。

格式:

ipV4:点分十进制,32位,由4个部分组成。例如: 192.168.0.1

ipV6:冒分十六进行,128位,例如:x:x:x 一个IPv6地址中间可能包含很长的一段0,可以把连续的一段0压缩为“::”

IP地址的分类: ABC DE特殊地址

(***)组播地址 D类IP地址在历史上被叫做多播地址(multicast address),即组播地址 224.0.0.0

到239.255.255.255

()广播地址 255.255.255.255 ()

本地回环地址 127.0.0.1 域名 localhost

java提供的ip地址

InetAddress

1.常用方法:

① getByName(String host) 根据参数获取InetAdress对象

② getHostName() 获取IP地址中域名的字符串形式

③ getHostAddress() 获取ip地址的字符串形式

④ getAllByName(String host)获取ip地址的数组

⑤ getLocalHost() 返回本机的ip地址

⑥ toString() 将ip地址转换为字符串。

代码

package com.demo;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
  1.常用方法:
    ① getByName(String host) 根据参数获取InetAdress对象
    ② getHostName() 获取IP地址中域名的字符串形式
    ③ getHostAddress() 获取ip地址的字符串形式
    ④ getAllByName(String host)获取ip地址的数组
    ⑤ getLocalHost()  返回本机的ip地址
    ⑥ toString() 将ip地址转换为字符串。

 */
public class IP地址 {
    public static void main(String[] args) throws UnknownHostException {
        /*InetAddress ip = InetAddress.getByName("www.baidu.com");
        System.out.println(ip.getHostName());
        System.out.println(ip.getHostAddress());*/
//          ④ getAllByName(String host)获取ip地址的数组

       /* InetAddress[] ips = InetAddress.getAllByName("www.baidu.com");
        for (InetAddress ip : ips) {
            System.out.println(ip);
        }*/

//         ⑤ getLocalHost()  返回本机的ip地址
        InetAddress ip1 = InetAddress.getLocalHost();
        System.out.println(ip1);
        InetAddress ip2 = InetAddress.getByName("localhost");
        System.out.println(ip2);
    }

}

UDP

概念

UDP:传输层协议。用户数据包协议(UDP,User Datagram Protocol)。

无连接的传输协议。

特点:

无连接、不可靠、快速传输。数据报包进行传输,包最大不会超过64k

使用场景:

实时直播,视频,网游。

java中提供的UDP协议的类

DatagramSocket:发送端/接收端:此类表示用来发送和接收数据报包的套接字

DatagramPacket:表示数据报包。实现无连接包投递服务

发送端

发送端步骤

1.发送端:

① 发送端端点对象:

DatagramSocket()

② 打包数据

DatagramPacket(byte[] buf, int length, InetAddress address, int port)

③ 发送

send(DatagramPacket p)

④ 关闭资源

close()

代码

package com.udpdemo;

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

/**
  1.发送端:
     ① 发送端端点对象:
        DatagramSocket()
     ② 打包数据
        DatagramPacket(byte[] buf, int length, InetAddress address, int port)
     ③ 发送
        send(DatagramPacket p)
     ④ 关闭资源
       close()
 */
public class 发送端 {
    public static void main(String[] args) throws IOException {
        DatagramSocket  ds = new DatagramSocket();
        byte[] bt = "你好".getBytes();
        DatagramPacket dp = new DatagramPacket(bt,bt.length, InetAddress.getByName("localhost"),9000);
        ds.send(dp);
        //接收
        byte[] bt1= new byte[1024];
        DatagramPacket dp1 = new DatagramPacket(bt1,bt1.length);
        ds.receive(dp1);
        System.out.println("发送端接收到的数据"+new String(dp1.getData(),0,dp1.getLength()));
        ds.close();
    }
}

接收端

① 接收端端点对象:DatagramSocket(int port)

② 接收数据报包,先创建空数据报包 然后接收数据。

DatagramPacket(byte[] buf, int length)

③ 接收:

receive(DatagramPacket p)

④ 关闭资源

close()

3.DatagramPacket常用方法:

① getLength() 获取数据报包中读取的数据的字节长度。

② getAddress() 接收端获取的发送端的ip地址

③ getPort() 接收端获取的发送端的端口号

代码

package com.udpdemo;

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

/**
  2.接收端:
    ① 接收端端点对象:DatagramSocket(int port)
    ② 接收数据报包,先创建空数据报包 然后接收数据。
 DatagramPacket(byte[] buf, int length)
    ③ 接收:
    receive(DatagramPacket p)
    ④ 关闭资源
     close()
  3.DatagramPacket常用方法:
     ① getLength() 获取数据报包中读取的数据的字节长度。
     ② getAddress() 接收端获取的发送端的ip地址
     ③ getPort() 接收端获取的发送端的端口号


 */
public class 接收端 {
    public static void main(String[] args) throws IOException {
        DatagramSocket  ds = new DatagramSocket(9000);
        byte[] bt = new byte[1024];
        //数据报包的创建 空白
        DatagramPacket dp = new DatagramPacket(bt,bt.length);
        //接收
        ds.receive(dp);
        System.out.println(new String(bt,0,dp.getLength()));
        //发送
        byte[] bt1 = "发送端你好".getBytes();
        //打数据报包
        DatagramPacket dp1 = new DatagramPacket(bt1, bt1.length,dp.getAddress(),dp.getPort());
        //接收端向发送端发送数据。
        ds.send(dp1);
        ds.close();
    }
}

简易聊天室

发送端代码

package com.demo;

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

public class 发送端 {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket();
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入您要发送到接收端的数据:");
            String msg = sc.nextLine();
            byte[] bt = msg.getBytes();
            //打数据报包
            DatagramPacket dp = new DatagramPacket(bt, bt.length, InetAddress.getLocalHost(),9000);
            //发送
            ds.send(dp);
            //结束
            if (msg.equals("exit")){
                break;
            }
            //接收
            byte[] bt1 = new byte[1024];
            //空的数据报包进行接收
            DatagramPacket dp1 = new DatagramPacket(bt1, bt1.length);
            //接收
            ds.receive(dp1);
            System.out.println("从接收端接收的信息为:"+new String(bt1,0,dp1.getLength()));
        }
        //关闭资源
        ds.close();
    }
}

接收端代码

package com.demo;

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

public class 接收端 {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket(9000);
        Scanner sc = new Scanner(System.in);
        while (true) {
            //接收
            byte[] bt = new byte[1024];
            DatagramPacket dp  = new DatagramPacket(bt,bt.length);
            ds.receive(dp);
            String rec = new String(bt, 0, dp.getLength());
            System.out.println("从发送端来的数据为:"+rec);
            //结束
            if (rec.equals("exit")){
                break;
            }
            //发送
            System.out.println("请输入向发送端发送的数据:");
            String msg = sc.nextLine();
            byte[] bt1 = msg.getBytes();
            DatagramPacket dp1 = new DatagramPacket(bt1,bt1.length,dp.getAddress(),dp.getPort());
            ds.send(dp1);
        }
        //关闭资源
        ds.close();
    }
}

广播地址

概述

广播地址: 255.255.255.255 所有

代码

package com.demo1;

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

/**
  1.广播地址: 255.255.255.255 所有。
 */
public class 广播地址 {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket();
        byte[] bt = "大家注意听课了。。。。".getBytes();
        DatagramPacket dp = new DatagramPacket(bt, bt.length, InetAddress.getByName("255.255.255.255"),9005 );
        ds.send(dp);
        ds.close();
    }
}

组播地址

概述

1.组播地址 D类IP地址在历史上被叫做多播地址(multicast address),即组播地址

224.0.0.0到239.255.255.255

2.组播 java提供的类: MulticastSocket

3.注意:

组播必须加入组播组 ,才能接受组播信息。

joinGroup(InetAddress mcastaddr)

发送端代码

package com.demo1;

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

/**
 1.组播地址 D类IP地址在历史上被叫做多播地址(multicast address),即组播地址
   224.0.0.0到239.255.255.255
 2.组播 java提供的类: MulticastSocket
 3.注意:
     组播必须加入组播组 ,才能接受组播信息。
 joinGroup(InetAddress mcastaddr)
 */
public class 组播地址发送端 {
    public static void main(String[] args) throws IOException {
        MulticastSocket ms = new MulticastSocket();
        byte[] bt = "大家注意听课了。。。".getBytes();
        DatagramPacket dp = new DatagramPacket(bt, bt.length,
                InetAddress.getByName("224.0.0.6"),9000);
        ms.send(dp);
        ms.close();

    }
}

接收端代码

package com.demo1;

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

public class 组播地址接收端 {
    public static void main(String[] args) throws IOException {
        MulticastSocket ms = new MulticastSocket(9000);
        byte[] bt = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bt, bt.length);
        //加入组播
        ms.joinGroup(InetAddress.getByName("224.0.0.6"));
        ms.receive(dp);
        System.out.println("从组播地址接收到的数据为:"+new String(bt,0,dp.getLength()));
        ms.close();

    }
}

TCP协议

概述

TCP:传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于

字节流的传输层通信协议

使用场景:

文件传输 需要保证数据完整性

TCP协议客户端

1.步骤:

① 创建客户端对象:

Socket(InetAddress address, int port)

② 发送/接收数据

getInputStream() 读取

getOutputStream()写入

代码

package com.tcpdemo;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

/**
  1.步骤:
   ① 创建客户端对象:
 Socket(InetAddress address, int port)
   ② 发送/接收数据
 getInputStream() 读取
 getOutputStream()写入

 */
public class 客户端 {
    public static void main(String[] args) throws IOException {
        Socket sc = new Socket(InetAddress.getByName("localhost"),9000);
        //发送数据
        OutputStream os = sc.getOutputStream();
        //写出
        os.write("服务器您好".getBytes());
        //关闭
        os.close();
        sc.close();
    }
}

TCP协议服务器端

1.步骤:

① 创建服务器端对象:

ServerSocket(int port)

② 等待连接:

accept() 侦听并接受到此套接字的连接。返回值就是连接到该服务器的客户端对象。

③ 读取客户端发送的信息

通过accept方法返回的Socket获取输入流。

代码

package com.tcpdemo;

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

/**
   1.步骤:
    ① 创建服务器端对象:
 ServerSocket(int port)
    ② 等待连接:
 accept()  侦听并接受到此套接字的连接。返回值就是连接到该服务器的客户端对象。
    ③ 读取客户端发送的信息
     通过accept方法返回的Socket获取输入流。
 */
public class 服务器端 {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(9000);
        //等待并监听 该方法一旦执行成功,意味着三次握手已经结束。
        Socket sc = ss.accept();
        //读取
        InputStream in = sc.getInputStream();
        int value = 0;
        byte[] bt = new byte[1024];
        while ((value=in.read(bt))!=-1){
            System.out.println(new String(bt,0,value));
        }
        //关闭
        in.close();
        ss.close();
    }
}

TCP协议细节问题

概述

如果使用的是循环读取,由于写入必须到达流的末尾或文件的末尾才能取到-1,

导致循环一直无法停止跳出,代码就没办法继续执行了。需要通过以下方法进行置为流的末尾。

① shutdownInput()

② shutdownOutput()

客户端代码

package com.tcpdemo1;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/**
  1.步骤:
   ① 创建客户端对象:
 Socket(InetAddress address, int port)
   ② 发送/接收数据
 getInputStream() 读取
 getOutputStream()写入
 2.细节问题:
    如果使用的是循环读取,由于写入必须到达流的末尾或文件的末尾才能取到-1,
    导致循环一直无法停止跳出,代码就没办法继续执行了。需要通过以下方法进行置为流的末尾。
    ① shutdownInput()
    ② shutdownOutput()


 */
public class 客户端 {
    public static void main(String[] args) throws IOException {
        Socket sc = new Socket(InetAddress.getByName("localhost"),9000);
        //发送数据
        OutputStream os = sc.getOutputStream();
        //写出
        os.write("服务器您好".getBytes());
        //置于流的末尾
        sc.shutdownOutput();
        //接收从服务器端发来的数据
        InputStream in = sc.getInputStream();
        int value = 0;
        byte[] bt = new byte[1024];
        while ((value = in.read(bt))!=-1){
            System.out.println(new String(bt,0,value));
        }
        //关闭
        os.close();
        in.close();
        sc.close();
    }
}

服务器端代码

package com.tcpdemo1;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
   1.步骤:
    ① 创建服务器端对象:
 ServerSocket(int port)
    ② 等待连接:
 accept()  侦听并接受到此套接字的连接。返回值就是连接到该服务器的客户端对象。
    ③ 读取客户端发送的信息
     通过accept方法返回的Socket获取输入流。
 */
public class 服务器端 {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(9000);
        //等待并监听 该方法一旦执行成功,意味着三次握手已经结束。
        Socket sc = ss.accept();
        //读取
        InputStream in = sc.getInputStream();
        int value = 0;
        byte[] bt = new byte[1024];
        while ((value=in.read(bt))!=-1){
            System.out.println(new String(bt,0,value));
        }
        System.out.println("=================");
        //服务器端向客户端发送数据
        OutputStream out = sc.getOutputStream();
        out.write("客户端您好".getBytes());
        //关闭
        in.close();
        out.close();
        ss.close();
    }
}

文件上传

原理

从客户端的硬盘上读取文件到客户端的java程序,然后通过java程序写入到服务器端的java程序,通过服务器端的java程序,写入到服务器的硬盘上。

客户端代码

package com.uploaddemo;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/**
  1.创建客户端对象
 2. 读取硬盘上的文件,向服务器端写入
 3.关闭资源
 */
public class 客户端 {
    public static void main(String[] args)throws IOException {
        Socket s = new Socket(InetAddress.getByName("localhost"),9000);
        //文件输入流
        FileInputStream fis = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\成功的阶梯.jpg"));
        //向服务器写入
        OutputStream os = s.getOutputStream();
        //读取硬盘上的文件,向服务器端写入
        int value =0;
        byte[] bt = new byte[1024];
        while ((value = fis.read(bt))!=-1){
            os.write(bt,0,value);
        }
        //关闭资源
        os.close();
        fis.close();
        s.close();
    }
}

服务器端代码

package com.uploaddemo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
  1.创建服务器端的对象
  2.等待客户端的连接
  3.接收从客户端来的文件,并且写入到服务器端的硬盘。
  4.关闭资源
 */
public class 服务器端 {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(9000);
        Socket s = ss.accept();
//        Socket的输入流
        InputStream in = s.getInputStream();
        //文件输出流
        FileOutputStream fos = new FileOutputStream(new File("day26b\\upload\\1.jpg"));
//        3.接收从客户端来的文件,并且写入到服务器端的硬盘。
        int value = 0;
        byte[] bt = new byte[1024];
        while ((value = in.read(bt))!=-1){
            fos.write(bt,0, value);
        }
//        关闭资源
        fos.close();
        in.close();
        ss.close();
    }
}

文件上传的重名问题

概述

文件上传时,由于文件名称是相同的,新的上传的文件会覆盖原有的。解决的办法:

① window系统重命名的方式

② UUID

全球唯一标识。

randomUUID() 获取UUID

多线程下的文件上传

客户端代码

package uploaddemo1;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
/**
  1.创建客户端对象
 2. 读取硬盘上的文件,向服务器端写入
 3.关闭资源
 */
public class 客户端 {
    public static void main(String[] args)throws IOException {
        Socket s = new Socket(InetAddress.getByName("localhost"),9000);
        //文件输入流
        FileInputStream fis = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\成功的阶梯.jpg"));
        //向服务器写入
        OutputStream os = s.getOutputStream();
        //读取硬盘上的文件,向服务器端写入
        int value =0;
        byte[] bt = new byte[1024];
        while ((value = fis.read(bt))!=-1){
            os.write(bt,0,value);
        }
        //关闭资源
        os.close();
        fis.close();
        s.close();
    }
}

服务器端代码

package uploaddemo1;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;

/**
  1.创建服务器端的对象
  2.等待客户端的连接
  3.接收从客户端来的文件,并且写入到服务器端的硬盘。
  4.关闭资源
 */
public class 服务器端 {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(9000);
        boolean flag = true;
        while (flag) {
            Socket s = ss.accept();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try(InputStream in = s.getInputStream();
                        FileOutputStream fos = new FileOutputStream(new File("day27a\\upload\\"+ UUID.randomUUID()+".jpg"));
                    ){
//                        3.接收从客户端来的文件,并且写入到服务器端的硬盘。
                        int value = 0;
                        byte[] bt = new byte[1024];
                        while ((value = in.read(bt))!=-1){
                            fos.write(bt,0, value);
                            Thread.sleep(2000);
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }).start();
        }
        ss.close();
    }
}

avatar
青山
悟已往之不谏 知来者之可追
一言
今日诗词
站点信息
本站访客数 :
本站总访问量 :