Java网络编程入门,包含网络相关概念、InetAddress类、套接字Socket、网络上传和下载文件等

Java学习-11-韩顺平老师

Java-网络编程入门

目录:

01-网络相关概念
02-InetAddress类
03-套接字Socket
04-网络上传和下载文件
05-UDP网络编程

网络编程相关概念

网络通信:

1.概念:两台设备之间通过网络实现数据传输。
2.网络通信:将数据通过网络从一台设备传输到另一台设备。
3.java.net包下提供了一系列的类或者接口,供程序员使用,完成网络通信。

网络:

1.概念:两台或者多台设备通过一个定物理设备连接起来构成的网络。
2.根据覆盖范围不同,对网络的进行分类:
	局域网:覆盖范围小。
	城域网:覆盖范围较大,可以覆盖一个城市。
	广域网:覆盖范围大,可以覆盖全国,甚至全球。

ip地址:

1.概念:用于唯一标识一网络中的每台计算机。
2.查看ip地址:ipconfig
3.ip地址表示形式:十进制 xxx.xxx.xxx.xxx
4.每个十进制范围0-255
5.ip地址组成 = 网络地址 + 主机地址。
6.ipv6是互联网工程任务组设计的用于替代ipv4的下一代ip协议。
7.ip地址分为五类:A,B,C,D,类,第一个十进制位每一级向左位移一位。

域名和端口号:

1.域名是ip地址的映射。
2.端口号用于标识计算机上某一个特定的网络程序。

网络协议:
TCP协议:

1.使用TCP协议前,需先 建立TCP连接,形成传输数据的通道。
2.传输前,采用“三次握手”方法,可以可靠传输。
3.TCP协议进行痛的两个应用进程:客户端、服务端。
4.在连接中可进行大数量的传输。
5.传输完成,需释放已建立的连接。

UDP协议:

1.将数据、源、目的封装成数据包,不需要建立连接。
2.每个数据报的大小限制在64k内。
3.因无需连接,故是不可靠的。
4.发送数据结束时无需释放资源(因为不是面向连接的),速度快。

InetAddress类

相关方法:

1.getLocalHost:获取主机InetAddress对象。
2.getByName:根据指定主机名/域名获取ip地址对象。
3.getHostName:获取InetAddress对象的主机名。
4.getHostAddress:获取InetAddress对象的地址。
public class InetAddress_ {
    public static void main(String[] args) throws UnknownHostException {
        // 获取本地主机的ip地址对象
        InetAddress inetAddress = InetAddress.getLocalHost();
        System.out.println(inetAddress); // DESKTOP-IFINBBF/127.0.0.1
        InetAddress byName = InetAddress.getByName("DESKTOP-IFINBBF");
        System.out.println(byName); // DESKTOP-IFINBBF/127.0.0.1
        // 通过域名或者主机名来获取ip地址对象
        InetAddress byName1 = InetAddress.getByName("www.baidu.com");
        System.out.println(byName1); // www.baidu.com/36.152.44.95
        // getHostName
        System.out.println(byName1.getHostName()); // www.baidu.com
        // getAddress 
        System.out.println(byName1.getHostAddress()); // 36.152.44.95
    }
}

套接字Socket

基本介绍:

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

TCP网络通信编程:

1.基于客户端-服务端网络通信。
2.底层使用的是TCP/IP协议。

基于Socket的TCP网络通信编程:
在这里插入图片描述

具体实例:

1.编写一个服务端,和一个客户端。
2.服务器在9999端口监听。
3.客户端连接到服务器段,发送"hello,serve",并接受服务器发的
  “hello,client”,在退出
4.服务器端接受到客户端发送的信息,输出,并发送“hello,client”

使用字节流实现
服务端:

public class SocketServe_ {
    public static void main(String[] args) throws IOException {
        // 创建一个ServeSocket对象
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端正在监听9999端口...");
        // 监听 9999 端口 并且返回一个socket对象
        Socket socket = serverSocket.accept();
        // 通过socket.getInputStream获得一个InputStream对象,接受客户端信息
        InputStream inputStream = socket.getInputStream();
        int len = 0;
        byte[] buf = new byte[1024];
        while ((len = inputStream.read(buf)) != -1){
            System.out.println(new String(buf,0,len));
        }
        
        // 通过socket.getOutputStream 获得一个OutputStream 向客户端发送信息
        String str = "hello,client";
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write(str.getBytes());
        // 标识已经发送完成,让服务器不要再等待,可以执行下面的代码了
        socket.shutdownOutput();
        System.out.println("服务端退出了");

        // 关闭socket和流,释放资源
        inputStream.close();
        outputStream.close();
        socket.close();
    }
}

客户端:

public class SocketClient_ {
    public static void main(String[] args) throws IOException {
        // 创建一个Socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        // 通过socket.getOutputStream 获得一个OutputStream 向服务端发送信息
        OutputStream outputStream = socket.getOutputStream();
        String str = "hello,server";
        outputStream.write(str.getBytes());
        // 标识已经发送完成,让服务器不要再等待,可以执行下面的代码了
        socket.shutdownOutput();

        // 通过socket.getInputStream获得一个InputStream对象,接受服务端信息
        InputStream inputStream = socket.getInputStream();
        int len = 0;
        byte[] buf = new byte[1024];
        while ((len = inputStream.read(buf)) != -1){
            System.out.println(new String(buf,0,len));
        }
        socket.shutdownInput();
        System.out.println("客户端退出了");

        // 关闭socket和流,释放资源
        outputStream.close();
        inputStream.close();
        socket.close();
    }
}

使用字符流实现:
服务端:

public class SocketServe01 {
    public static void main(String[] args) throws IOException {
        // 创建一个ServeSocket对象
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端正在监听9999端口...");
        // 监听 9999 端口 并且返回一个socket对象
        Socket socket = serverSocket.accept();
        // 通过socket.getInputStream获得一个InputStream对象,
        // 再通过InputStreamReader 转换成字符流,接受服务端信息
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        // 只能使用一次readLine,否则下面代码不再执行
        System.out.println(br.readLine());
        // 通过socket.getOutputStream 获得一个OutputStream
        // 再将字节流通过OutputStreamWriter装换成字符流,再向服务端发送信息
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        String str = "hello,client";
        bw.write(str);
        // 使用bw.newLine 表示写入完成,就不需要socket.shutdownOutput()了
        // 但是接受方,必须使用 readLine 接收
        bw.newLine();
        //使用Writer子类 一定要flush以下,不然没有真正的写入socket中
        bw.flush();
        System.out.println("服务端退出了");

        // 关闭socket和流,释放资源
        br.close();
        bw.close();
        socket.close();
    }
}

客户端:

public class SocketClient01 {
    public static void main(String[] args) throws IOException {
        // 创建一个Socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        // 通过socket.getOutputStream 获得一个OutputStream
        // 再将字节流通过OutputStreamWriter装换成字符流,再向服务端发送信息
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        String str = "hello,server";
        bw.write(str);
        // 使用bw.newLine 表示写入完成,就不需要socket.shutdownOutput()了
        // 但是接受方,必须使用 readLine 接收
        bw.newLine();
        // 使用Reader子类写入必须flush一下,不然没有真正写入
        bw.flush();
        // 标识已经发送完成,让服务器不要再等待,可以执行下面的代码了
        // socket.shutdownOutput();

        // 通过socket.getInputStream获得一个InputStream对象,
        // 再通过InputStreamReader 转换成字符流,接受服务端信息

        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        System.out.println(br.readLine());
        System.out.println("客户端退出了");

        // 关闭socket和流,释放资源
        bw.close();
        br.close();
        socket.close();
    }
}

网络上传和下载文件

1.上传文件:

1.编写一个服务端和客户端
2.服务器端再9999接口监听
3.客户端接受服务端,发送的一张图片 e:\\a.png
4.服务端接受图片,保存到src目录下,并发送服务端收到了图片,在退出
5.客户端接受服务端信息,并打印出来,在退出
6.使用到StreamUtils.java这个自己封装的工具类

自定义工具类 StreamUtils.java : 实现文件读取 字节数组 和 字符串之间的转换

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
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();	
	}

}

服务端:

public class UploadServe {
    public static void main(String[] args) throws Exception {
        // 建立服务器
        ServerSocket serverSocket = new ServerSocket(9999);
        // 监听9999端口
        System.out.println("服务端正在监听 9999 端口,等待接受数据");
        Socket socket = serverSocket.accept();
        // 通过 socket.getInputStream() 获得一个InputStream流来读取网络传输数据
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        byte[] bytes = StreamUtils.streamToByteArray(bis);
        // 标识已经读写完成
        socket.shutdownInput();
        // 将读取成功的数据写入内存 src\\a.jpg
        BufferedOutputStream bos1 = new BufferedOutputStream(new FileOutputStream("src\\a.jpg"));
        bos1.write(bytes);
        // 刷新以下
        bos1.flush();
        bos1.close();
        // 返回一个 “文件读取成功”
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        bos.write("文件读取成功".getBytes());
        // 标识已经写入完成
        socket.shutdownOutput();

        // 关闭相关资源
        bis.close();
        bos.close();
        socket.close();
        serverSocket.close();
    }
}

客户端:

public class UploadClient {
    public static void main(String[] args) throws Exception {
        // 常见一个socket
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        //将 e:\\a.jpg 读出,并放在byte数组中,使用StreamUtils工具
        byte[] buf; // 存储图片数组
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("e:\\a.jpg"));
        buf = StreamUtils.streamToByteArray(bis);
        // 通过socket获得一个OutPutStream 来发送数据
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        // 将字符数组写入到网络中
        bos.write(buf);
        // 添加写入完成表示符
        socket.shutdownOutput();

        // 接受服务端传来的数据
        BufferedInputStream bis1 = new BufferedInputStream(socket.getInputStream());
        String str = StreamUtils.streamToString(bis1);
        System.out.println(str);
        System.out.println("客户端退出");

        // 关闭相关流,释放资源
        bis.close();
        bos.close();
        bis1.close();
        socket.close();
    }
}

2.下载文件

1.编写一个服务端和客户端
2.服务器端再9999接口监听
3.服务端发送需要下载图片的名称 "伤感头像.jpg"
4.服务端接受图片名称,从e盘目录下返回图片给客户端,如果没有"伤感头像.jpg",就返回"默认头像.jpg"
5.客户端接受到数据后保存到本地 d:\\xxx.jpg
6.使用到StreamUtils.java这个自己封装的工具类

StreamUtils.java: 仍然使用上面自己定义的工具类

服务端:

public class DownLoadServer {
    public static void main(String[] args) throws Exception {
        // 创建监听器
        ServerSocket serverSocket = new ServerSocket(9999);
        // 监听9999端口
        System.out.println("服务端正在监听9999端口,等待接受文件名称");
        Socket socket = serverSocket.accept();

        // 创建接受文件名称
        InputStream inputStream = socket.getInputStream();
        byte[] b = new byte[1024];
        int len = 0;
        String downFileName = "";
        while ((len = inputStream.read(b)) != -1){
            downFileName += new String(b,0,len);
        }
        String resFileName = "";
        if("伤感图片.jpg".equals(downFileName)){
            resFileName = "e:\\伤感图片.jpg";
        }else{
            resFileName = "e:\\默认图片.jpg";
        }
        System.out.println(resFileName);
        // 通过文件名从src目录中读取文件,转换成byte[]数组
        BufferedInputStream bis1 = new BufferedInputStream(new FileInputStream(resFileName));
        byte[] bytes = StreamUtils.streamToByteArray(bis1);

        // 将数据通过 socket.getOutputStream 发送给客户端
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        bos.write(bytes);
        // 标识已经写入完成
        socket.shutdownOutput();

        // 关闭相关资源
        inputStream.close();
        bis1.close();
        bos.close();
        socket.close();
        serverSocket.close();
    }
}

客户端:

public class DownloadClient {
    public static void main(String[] args) throws Exception {
        // 我这里是对本机操作,所以使用的getLocalHost获取ip地址,
        // 如果其他服务器就是用 InetAddress.getByName() + ip 地址来获取
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);

        // 发送图片名称
        String downLoadName = "伤感图片.jpg";
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write(downLoadName.getBytes());
        socket.shutdownOutput(); // 标识已经写入完成

        // 当服务器返回数据,就收服务器返回的数据
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        byte[] bytes = StreamUtils.streamToByteArray(bis); // 获取文件数据的字节数组形式

        // 将数据写入到e盘下
        BufferedOutputStream bos1 = new BufferedOutputStream(new FileOutputStream("d:\\" + downLoadName));
        bos1.write(bytes); // 写入e盘

        // 关闭相关资源
        bis.close();
        outputStream.close();
        bos1.close();
        socket.close();
    }
}

UDP网络编程

应用案列:

1.编写一个接受接收端A,和一个发送端B.
2.接收端A在9999端口等待接受数据(receive)
3.发送端A向接受B发送数据"hello,明天吃火锅"
4.接受端B接受到 A发送的信息,回复"好的,明天见",再退出
5.接收到接受到数据后再退出

发送方:

public class Send {
    public static void main(String[] args) throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket(8888);
        // 创建一个 DatagramPacket 并且指定发送的ip地址和端口号、
        byte[] data = "hello,明天吃火锅".getBytes();
        DatagramPacket datagramPacket = new DatagramPacket(data,data.length, InetAddress.getLocalHost(),9999);
        datagramSocket.send(datagramPacket);

        // 接收接收方数据
        byte[] bytes = new byte[1024];
        DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
        datagramSocket.receive(packet);

        // 拆包
        byte[] data1 = packet.getData();
        int length = packet.getLength();
        String s = new String(data1, 0, length);
        System.out.println(s);
    }
}

接收方:

public class Receive {
    public static void main(String[] args) throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket(9999);
        byte[] bytes = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(bytes,1024);
        // 接受数据,并放在 datagramPacket
        System.out.println("接受方正在端口9999,等待接受数据");
        datagramSocket.receive(datagramPacket);

        // 拆包
        byte[] data = datagramPacket.getData();
        int length = datagramPacket.getLength();
        String s = new String(data, 0, length);
        System.out.println(s);

        // 发送数据给发送方
        byte[] data1 = "好的,明天见".getBytes();
        DatagramPacket packet = new DatagramPacket(data1,data1.length, InetAddress.getLocalHost(),8888);
        datagramSocket.send(packet);

    }
}

网络编程入门小结,欢迎大家交流学习!
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值