韩顺平java-网络编程基础总结


一、网络基础

1.网络通信

概念:两台主机之间通过网络实现通信(数据传输)。
java.net包下提供了网络通信的一系列类或接口。

2.网络

概念:两台或多态设备通过一些物理设备连接形成网络。
分类:(根据覆盖范围不同)
局域网:一个教室或机房。
城域网:覆盖一个城市。
广域网:全国甚至全球。

3.ip地址

概念:唯一标识网络中的每台计算机。
表示:点分十进制 xx.xx.xx.xx (每一个十进制数的范围0~255)。
组成:网络地址+主机地址,如192.168.16.69
ipv4和ipv6:
ipv4:网络地址有限
ipv6:替代ipv4的下一代ip协议,地址数量号称可以为全世界的每一粒沙子都编上一个地址。
物联网:称万物皆可联网,ipv6的出现解决了多种接入设备连入互联网的问题。
在这里插入图片描述
在这里插入图片描述
ipv6为:冒分16进制。

4.ipv4地址分类

在这里插入图片描述
abc的网络号分别占1个,2个,3个字节。

5.域名

www.baidu.com
因ip地址不好记,为了方便记忆,将ip地址映射成了域名。

6.端口号

概念:表示计算机上某个特定的网络程序。
表示形式:整数,范围在0~65535
0~1024端口号已经被占用,比如 ssh 22,ftp 21,smtp 25,http 80
常见的网络程序端口号:
tomcat:8080
mysql:3306
oracle:1521
sqlserver:1433

7.网络通信协议

(1)tcp/ip协议

tcp/ip协议:传输控制协议/互联网协议,又叫网络通讯协议,是internet最基本的协议。

比如任何人直接的交流(通讯)靠语言,那么语言就是一种协议。 现在计算机和计算机之间的传递数据,也是按照一种规定好的协议方式。

(2)网络通信协议

在这里插入图片描述

8.TCP和UDP

(1)TCP协议

1.先建立TCP连接,形成传输数据通道
2.传输前采用“三次握手”方式,是可靠的。
3.TCP通信时的两个应用进程:客户端/服务端
4.在连接中可进行大数据量的传输。
5.传输完毕,须先释放建立的连接,效率较低。

(2)UDP协议

1.将数据、源、目的封装成数据包,不需要建立连接。
2.每个数据报大小在64K内
3.因无需连接,故不可靠
4.发送数据结束后不用释放资源,速度快。
5.例如发短信,通知。

二、InetAddress类

1.getLocalHost()可得到主机名和对应的本机的ip地址对象。
2.getByName()可根据主机名或域名得到对应的ip地址对象。
3.getHostName()->根据ip地址对象可分别得到其中的域名/主机名。
4.getHostAddress()->根据ip地址对象可分别得到其中的ip地址。

//1.获取本机的InetAddress对象,getLocalHost,可得到主机名和对应的本机的ip地址对象
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println("1."+localHost);
//2.3.根据指定的主机名/域名获取ip地址对象 getByName,可得到根据域名或主机名 得到对应的 域名或主机名/ip地址
        InetAddress host = InetAddress.getByName("DESKTOP-9OTH615");
        System.out.println("2."+host);
        InetAddress yuming = InetAddress.getByName("www.baidu.com");
        System.out.println("3."+yuming);
//4.获取InetAddress对象的主机名getHostName->根据ip地址对象可分别得到其中的域名/主机名
        String hostName = host.getHostName();
        String yumingHostName = yuming.getHostName();
        System.out.println("4."+hostName+" "+yumingHostName);
//5.获取InetAddress对象的地址getHostAddress->根据ip地址对象可分别得到其中的ip地址
        String hostAddress = host.getHostAddress();
        String hostAddress1 = yuming.getHostAddress();
        System.out.println("5."+hostAddress+" "+hostAddress1);

在这里插入图片描述
在这里插入图片描述

三、Socket套接字

1.Socket开发网络应用程序被广泛采用,以至于成为事实上的标准。
2.通信的两端都要有Socket,是两台机器间通信的端点
3.网络通信就是Socket间的通信
4.Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输
5.一般主动发起通信的应用程序属客户端等待通信请求的为服务端

Socket就像是两个电源之间的插头,而创建的连接就相当于电源线。

数据在两个Socket间通过IO传输:
在这里插入图片描述

四、TCP网络通信编程

1.基本介绍

(1)基于客户端/服务端的网络编程。
(2)底层使用TCP/IP协议
(3)基于Socket的TCP编程。

2.使用字节流

在这里插入图片描述
在这里插入图片描述

/*
服务器
 */
public class SocketTCP01Server {
    public static void main(String[] args) throws IOException {
    //在本机的9999端口监听,等待连接
    //(要求在本机没有其他服务在监听9999端口)
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端在9999端口监听..,等待连接");
        //当没有客户端连接9999端口时,程序会阻塞,等待连接
        Socket socket = serverSocket.accept();
        //当有客户端连接时,返回socket对象,程序继续
        System.out.println("服务端连接成功");
        //通过socket.getInputStream();读取数据通道的数据。
        InputStream inputStream = socket.getInputStream();
       byte[] bytes=new byte[1024];
       int readLine=0;
        while ((readLine=inputStream.read(bytes))!=-1){
            System.out.println(new String(bytes,0,readLine));
        }
        //关闭流和socket
        inputStream.close();
        socket.close();
        serverSocket.close();
    }
}

/*
客户端
 */
public class SocketTCP01Client {
    public static void main(String[] args) throws IOException {
    //连接本机的9999端口,如果连接成功,则会返回一个socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端已连接,准备发送数据");
        //通过socket.getOutputStream();得到与socket关联的输出流对象。
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello,server".getBytes(StandardCharsets.UTF_8));

        //关闭资源
        outputStream.close();
        socket.close();
        System.out.println("客户端退出");

    }
}

在这里插入图片描述
在这里插入图片描述

serverSocket可以创建很多的socket,它只要有一次accept就会有一个socket。
在这里插入图片描述
在这里插入图片描述

/*
服务端
 */
public class SocketTCP02Server {
    public static void main(String[] args) throws IOException {
        //z1
        ServerSocket serverSocket = new ServerSocket(9998);
        //z2
        Socket socket = serverSocket.accept();
        //z3
        OutputStream os = socket.getOutputStream();
        os.write("hello server".getBytes());
        //设置输出结束标记
        socket.shutdownOutput();
//接收服务端发送的数据 z4
        InputStream is = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int readLine=0;
        while ((readLine=is.read(bytes))!=-1){
            System.out.println(new String(bytes,0,readLine));
        }

        //释放资源
        is.close();
        os.close();
        socket.close();
        serverSocket.close();

    }
}
/*
客户端
 */
public class SocketTCP02Client {
    public static void main(String[] args) throws IOException {
        //z1
        Socket socket = new Socket(InetAddress.getLocalHost(), 9998);
        //z2
        InputStream is = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int readLen=0;
        while ((readLen=is.read(bytes))!=-1){
            System.out.println(new String(bytes,0,readLen));
        }
        //z3 发送hello client
        OutputStream os = socket.getOutputStream();
        os.write("hello client".getBytes());
        //关闭资源
        os.close();
        is.close();
        socket.close();
    }
}

当写入结束时,设置一个写入结束标记:socket.shutdownOutput();

3.使用字符流

使用字符流进行编写:
在这里插入图片描述

/**
 * 服务端
 */
public class SocketTCP03Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        Socket socket = serverSocket.accept();
        InputStream is = socket.getInputStream();
        //?IO读取,使用字符流 用InputStreamReader将InputStream转成字符流
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String s = br.readLine();
        System.out.println(s);//使用字符流读取后输出也比较方便。
        System.out.println("Server读取完毕");
        //回送给客户端信息
        OutputStream os = socket.getOutputStream();
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
        bw.write("hello client,我是Server");
        bw.newLine();
        bw.flush();
        //关闭资源
        bw.close();//关闭流时,只需关闭外层流即可
        br.close();
        socket.close();
        serverSocket.close();


    }
}

/**
 *客户端
 */
public class SocketTCP03Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        OutputStream os = socket.getOutputStream();
        //1.使用字符流进行写入
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
        bw.write("hello server,我是Client");
        bw.newLine();//字符流也可以用newLine()作为自己的写入结束标记
        bw.flush();//使用字符流写入,需要手动刷新,否则数据不会写入数据通道。
        //2.接收信息
        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String s = br.readLine();
        System.out.println(s);

        //关闭资源
        br.close();
        bw.close();
        socket.close();

    }
}

在这里插入图片描述
在这里插入图片描述
即字节输入流转为字符输入流并进行输入:

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

字节输出流转为字符输出流并进行输出:

 OutputStream os = socket.getOutputStream();
 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
 bw.write("hello client,我是Server");
 bw.newLine();
 bw.flush();

4.网络上传图片

(1)基本介绍及思路分析

在这里插入图片描述
1.首先把磁盘上的文件读到程序里面去。
2.然后把图片放在一个字节数组,因为图片是二进制的,放在一个字节数组比较合理。
3.socket获取输出流。
4.传到服务端后,首先要通过一个socket获取一个输入流,先保存在一个服务器的字节数组(内存)中去。
服务端再获取一个输出流,将获取到的数据输出到一个指定的目录。(刷新打磁盘上。)
在这里插入图片描述

(2)具体实现

StreamUtils工具类:

/**
 * 此类用于演示关于流的读写方法
 *
 */
public class StreamUtils {
	/**
	 * 功能:将输入流转换成byte[], 即可以把文件的内容读入到byte[]
	 * @param is
	 * @return
	 * @throws Exception
	 */
	public static byte[] streamToByteArray(InputStream is) throws Exception{
		ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
		byte[] b = new byte[1024];//字节数组
		int len;
		while((len=is.read(b))!=-1){//循环读取
			bos.write(b, 0, len);//把读取到的数据,写入bos	
		}
		byte[] array = bos.toByteArray();//然后将bos 转成字节数组
		bos.close();
		return array;
	}
	/**
	 * 功能:将InputStream转换成String
	 * @param is
	 * @return
	 * @throws Exception
	 */
	
	public static String streamToString(InputStream is) throws Exception{
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder builder= new StringBuilder();
		String line;
		while((line=reader.readLine())!=null){
			builder.append(line+"\r\n");
		}
		return builder.toString();
		
	}

}

StreamUtils工具类:
1.将输入流转为字节数组。
2.将输入流转为字符串。

/**
 * 服务端:将图片输出到磁盘上
 */
public class TCPFileUploadServer {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8888);
        Socket socket = serverSocket.accept();
        //服务端接收客户端发来的图片
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        byte[] bytes = StreamUtils.streamToByteArray(bis);
        //获取本机上的输出流
        String descSrc = "src\\water.png";
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(descSrc));
        //图片的字节数组写入输出流。
        bos.write(bytes);
     //输出完毕,发送收到图片给客户端
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write("收到图片");
        bw.newLine();
        bw.flush();
        //关闭资源
        bw.close();
        bis.close();
        bos.close();
        socket.close();
        serverSocket.close();
    }
}
/**
 *将图片以字节数组的形式发给服务端
 */
public class TCPFileUploadClient {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
        //1.客户端发送照片
        //1.1读取磁盘上的文件
        String path="D:\\桌面\\qie.png";
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
        //1.2转为字节数组
        byte[] bytes = StreamUtils.streamToByteArray(bis);
        //2.将图片输出到服务端
        OutputStream os = socket.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);
        bos.write(bytes);
        socket.shutdownOutput();//设置写入的结束标记
//收到服务端发送的信息,以字符流的形式发送,以字符流的形式输出
//        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//        String s = br.readLine();
        InputStream inputStream = socket.getInputStream();
        String s = StreamUtils.streamToString(inputStream);
        System.out.println(s);
        //关闭资源
//        br.close();
        bos.close();
        bis.close();
        socket.close();

    }
}

在这里插入图片描述

五、UDP网络通信编程

UDP在网络开发中用的较少,大体知道是怎么开发的,特点是什么就行。

(1)DatagramSocket和DatagramPacket

DatagramSocket:数据报套接字,用于发送和接收数据报。
DatagramPacket:封装了UDP数据报。包含发送端和接收端的ip和端口。

(2)基本介绍

1.DatagramSocket和DatagramPacket实现了基于UDP的网络编程程序。
2.UDP数据包封装在DatagramPacket中,通过DatagramSocket发送和接收,但不能保证UDP数据包一定能够安全的送到目的地,也不能确定什么时间可以抵达。
3.DatagramPacket封装UDP数据包对象中包含发送端和接收端的ip地址和端口号。
4.因为封装了各自的ip地址和端口号,因此无须建立发送方和接收方的连接。

(3)基本流程

在这里插入图片描述
在这里插入图片描述
UDP没有服务端和客户端的概念了,两者都可以是发送端和接收端。

(4)UDP案例

在这里插入图片描述
在这里插入图片描述

/**
 *接收端A
 */
public class UDPReceiverA {
    public static void main(String[] args) throws IOException {
     //1.创建一个DatagramSocket对象,准备在9999接收数据
        DatagramSocket socket = new DatagramSocket(9999);

        //2.构建一个DatagramPacket对象,准备接收数据
        //一个数据报最大为64K
        byte[] buf = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);

        //3.调用 接收方法,将通过网络传输的DatagramPacket对象  填充到packet对象
        //若有数据包发送到9999端口,就会接收到数据
        //否则,就会阻塞等待。
        System.out.println("接收端A 等待接收数据");
        socket.receive(packet);

        //4.可以把packet进行拆包, 取出数据,  并显示
        int length = packet.getLength();//实际接收到的数据字节长度
        byte[] data = packet.getData();//接收到数据
        String s = new String(data,0, length);//少了个0
        System.out.println(s);

        //4.2向B端发送资源


        //5.关闭资源
        socket.close();
        System.out.println("A端退出");
    }
}

/**
 *发送端B
 */
public class UDPSenderB {
    public static void main(String[] args) throws IOException {
//1.创建DatagramSocket 准备在9998端口接收数据
        DatagramSocket socket = new DatagramSocket(9998);

        //2.将需要发送的数据,封装到 DatagramPacket对象
        byte[] data = "hello, 明天吃火锅".getBytes();

        //说明:封装的 DatagramPacket对象 data内容字节数组 , data.length , 主机(IP) , 端口
        DatagramPacket packet =
                new DatagramPacket(data, data.length, InetAddress.getByName("10.66.116.28"), 9999);

   socket.send(packet);
   //关闭资源
        socket.close();
        System.out.println("B端退出");
    }
}

作业

在这里插入图片描述

/**
 * 服务端:将图片输出到磁盘上
 */
public class TCPFileUploadServer {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8888);
        Socket socket = serverSocket.accept();
        //服务端接收客户端发来的图片
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        byte[] bytes = StreamUtils.streamToByteArray(bis);
        //获取本机上的输出流
        String descSrc = "src\\water.png";
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(descSrc));
        //图片的字节数组写入输出流。
        bos.write(bytes);
     //输出完毕,发送收到图片给客户端
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write("收到图片");
        bw.newLine();
        bw.flush();
        //关闭资源
        bw.close();
        bis.close();
        bos.close();
        socket.close();
        serverSocket.close();
    }
}
/**
 *将图片以字节数组的形式发给服务端
 */
public class TCPFileUploadClient {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
        //1.客户端发送照片
        //1.1读取磁盘上的文件
        String path="D:\\桌面\\qie.png";
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
        //1.2转为字节数组
        byte[] bytes = StreamUtils.streamToByteArray(bis);
        //2.将图片输出到服务端
        OutputStream os = socket.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);
        bos.write(bytes);
        socket.shutdownOutput();//设置写入的结束标记
//收到服务端发送的信息,以字符流的形式发送,以字符流的形式输出
//        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//        String s = br.readLine();
        InputStream inputStream = socket.getInputStream();
        String s = StreamUtils.streamToString(inputStream);
        System.out.println(s);
        //关闭资源
//        br.close();
        bos.close();
        bis.close();
        socket.close();

    }
}

工具类:

/**
 * 此类用于演示关于流的读写方法
 *
 */
public class StreamUtils {
	/**
	 * 功能:将输入流转换成byte[], 即可以把文件的内容读入到byte[]
	 * @param is
	 * @return
	 * @throws Exception
	 */
	public static byte[] streamToByteArray(InputStream is) throws Exception{
		ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
		byte[] b = new byte[1024];//字节数组
		int len;
		while((len=is.read(b))!=-1){//循环读取
			bos.write(b, 0, len);//把读取到的数据,写入bos	
		}
		byte[] array = bos.toByteArray();//然后将bos 转成字节数组
		bos.close();
		return array;
	}
	/**
	 * 功能:将InputStream转换成String
	 * @param is
	 * @return
	 * @throws Exception
	 */
	
	public static String streamToString(InputStream is) throws Exception{
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder builder= new StringBuilder();
		String line;
		while((line=reader.readLine())!=null){
			builder.append(line+"\r\n");
		}
		return builder.toString();
		
	}

}

六、代码学习思路

先理清思路,再开始自己写代码,遇到问题时再会看视频找出问题,最后再总结反思。
双向并举,一般同时学两个东西是最快的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值