网络编程
-网络相关概念
网络通信
- 概念:两台设备之间通过网络实现数据传输
- 网络通信:将数据通过网络从一台设备传输到另一台设备
- java.net包下提供了一系列的类或接口,供程序员使用,完成网络通信
网络
- 概念:两台或多台设备通过一定物理设备连接起来构成了网络
- 根据网络的覆盖范围不同,对网络进行分类:
- 局域网:覆盖范围最小,仅仅覆盖一个教室或一个机房
- 城域网:覆盖范围较大,可以覆盖一个城市
- 广域网:覆盖范围最大,可以覆盖全国,甚至全球,万维网是广域网的代表
IP地址
- 概念:用于唯一标识网络中的每台计算机
- 查看IP地址:ipconfig
- IP地址的表示形式:点分十进制xx.xx.xx.XX
- 每一个十进制数的范围:0~255
- IP地址的组成=网络地址+主机地址,比如:192.168.16.69
- lPv6是互联网工程任务组设计的用于替代IPv4的下一代IP协议,其地址数量号称可以为全世界的每一粒沙子编上一个地址
- 由于IPv4最大的问题在于网络地址资源有限,严重制约了互联网的应用和发展。IPv6的使用,不仅能解决网络地址资源数量的问题,而且也解决了多种接入设备连入互联网的障碍
域名
- www.baidu.com
- 好处:为了方便记忆,解决记ip的困难
- 概念:将ip地址映射成域名
端口号
概念:用于标识计算机上某个特定的网络程序
表示形式:以整数形式,范围0~65535
0~1024已经被占用,比如 ssh 22, ftp 21,smtp 25 http 804
常见的网络程序端口号:
tomcat :8080
mysql:3306
oracle:1521
sqlserver:1433
网络通信协议
协议(tcp/ip)
TCP/lP(Transmission Control Protocol/Internet Protocol)的简写中文译名为传输控制协议/因特网互联协议,又叫网络通讯协议,这个协议是Internet最基本的协议、Internet国际互联网络的基础,简单地说,就是由网络层的IP协议和传输层的TCP协议组成的。
TGP 和 UDP
TCP协议:
- 使用TCP协议前,须先建立TCP连接,形成传输数据通道
- 传输前,采用"三次握手"方式,是可靠的
- TCP协议进行通信的两个应用进程:客户端、服务端
- 在连接中可进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低
UDP协议:
- 将数据、源、目的封装成数据包,不需要建立连接
- 每个数据报的大小限制在64K内
- 因无需连接,故是不可靠的
- 发送数据结束时无需释放资源(因为不是面向连接的),速度快
- 举例: 厕所通知: 发短信
-InetAddress类
相关方法
- 获取本机InetAddress对象 getLocalHost
- 根据指定主机名/域名获取ip地址对象 getByName
- 获取InetAddress对象的主机名 getHostName
- 获取InetAddress对象的地址 getHostAddress
练习
package inetaddress; import java.net.InetAddress; import java.net.UnknownHostException; /** * 1. 获取本机InetAddress对象 getLocalHost * 2. 根据指定主机名/域名获取ip地址对象 getByName * 3. 获取InetAddress对象的主机名 getHostName * 4. 获取InetAddress对象的地址 getHostAddress */ public class Practice1 { public static void main(String[] args) throws UnknownHostException { InetAddress inetAddress=null; //1. 获取本机InetAddress对象 getLocalHost inetAddress=InetAddress.getLocalHost(); System.out.println(inetAddress); //2. 根据指定主机名/域名获取ip地址对象 getByName inetAddress=InetAddress.getByName("DESKTOP-DVFTQAF"); System.out.println(inetAddress); inetAddress=InetAddress.getByName("www.google.com"); System.out.println(inetAddress); //3. 获取InetAddress对象的主机名 getHostName String hostName=inetAddress.getHostName(); System.out.println(hostName); //4. 获取InetAddress对象的地址 getHostAddress String hostAddress=inetAddress.getHostAddress(); System.out.println(hostAddress); } }
-Socket
- 基本介绍
- 套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准。
- 通信的两端都要有Socket,是两台机器间通信的端点
- 网络通信其实就是Socket间的通信。
- Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输
- 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端
-TCP网络通信编程
基本介绍
- 基于客户端一服务端的网络通信
- 底层使用的是TCP/IP协议
- 应用场景举例:客户端发送数据,服务端接受并显示
- 基于Socket的TCP编程
TCP字节流编程案例
服务端代码
package socket; import java.io.*; import java.net.ServerSocket; import java.net.Socket; /** * 1.编写一个服务器端, 和一个客户端 * 2.服务器端在 9999端口监听! * 2.客户端连接到服务器端,发送"hello,server”,并接收服务器端回发的"hello,client",再退出 * 4. 服务器端接收到 客户端发送的 信息,输出,并发送"hello, client",再退出 */ public class SocketTCPTest01Server { public static void main(String[] args) throws IOException { //创建服务器端套接字 ServerSocket serverSocket=new ServerSocket(9999); System.out.println("服务端等待连接,端口:9999"); //监听连接并返回一个连接套接字 Socket socket=serverSocket.accept(); System.out.println("服务端建立连接成功,可以读取数据"); //获取连接输入流,读取数据并打印 InputStream inputStream=socket.getInputStream(); byte[] bytes=new byte[1024]; int readlen; while((readlen= inputStream.read(bytes))!=-1){ System.out.print("读取到数据:"+new String(bytes,0,readlen)); } System.out.println(); //获取连接输出流,输出信息 String str="hello,client"; OutputStream outputStream=socket.getOutputStream(); outputStream.write(str.getBytes()); socket.shutdownOutput(); System.out.println("服务端发送数据成功"); //关闭流及套接字 inputStream.close(); outputStream.close(); socket.close(); System.out.println("服务端已关闭流及连接"); } }
客户端代码
package socket; import java.io.*; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; /** * 1.编写一个服务器端, 和一个客户端 * 2.服务器端在 9999端口监听! * 2.客户端连接到服务器端,发送"hello,server”,并接收服务器端回发的"hello,client",再退出 * 4. 服务器端接收到 客户端发送的 信息,输出,并发送"hello, client",再退出 */ public class SocketTCPTest01Client { public static void main(String[] args) throws IOException { //获取主机的网络信息 InetAddress inetAddress=InetAddress.getLocalHost(); //创建套接字 Socket socket=new Socket(inetAddress,9999); System.out.println("客户端获取套接字成功"); //获取输出流,发送数据及结束标识 String str="hello,server"; OutputStream outputStream=socket.getOutputStream(); outputStream.write(str.getBytes()); System.out.println("客户端发送数据成功"); socket.shutdownOutput(); //获取连接输入流,读取数据并打印 InputStream inputStream=socket.getInputStream(); byte[] bytes=new byte[1024]; int readlen; while((readlen= inputStream.read(bytes))!=-1){ System.out.print("读取到数据:"+new String(bytes,0,readlen)); } System.out.println(); //关闭流与套接字 outputStream.close(); inputStream.close(); socket.close(); System.out.println("客户端已关闭流及连接"); } }
TCP字符流编程案例
服务端
package socket; import java.io.*; import java.net.ServerSocket; import java.net.Socket; /** * 编写一个服务端,和一个客户端服务端,使用字符流传输 * 在 9999端口监听 * 客户端连接到服务端,发送"helo, server”,并接收服务端回发的"hello,client”,再退出 * 服务端接收到 客户端发送的 信息,输出,并发送"hello, client",再退出 */ public class SocketTCPTest02Server { public static void main(String[] args) throws IOException { //创建服务端套接字并指定端口 ServerSocket serverSocket=new ServerSocket(9999); System.out.println("等待接收连接"); //阻塞等待接受连接 Socket socket=serverSocket.accept(); System.out.println("收到连接"); //字符流读取数据 String str; BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream())); while((str=bufferedReader.readLine())!=null){ System.out.println(str); } System.out.println("读取数据结束"); //字符流发送数据 BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); bufferedWriter.write("hello, client"); bufferedWriter.flush(); socket.shutdownOutput(); //关闭流与套接字 bufferedReader.close(); bufferedWriter.close(); socket.close(); System.out.println("已关闭流与套接字"); } }
客户端
package socket; import java.io.*; import java.net.InetAddress; import java.net.Socket; /** * 编写一个服务端,和一个客户端服务端,使用字符流传输 * 在 9999端口监听 * 客户端连接到服务端,发送"helo, server”,并接收服务端回发的"hello,client”,再退出 * 服务端接收到 客户端发送的 信息,输出,并发送"hello, client",再退出 */ public class SocketTCPTest02Client { public static void main(String[] args) throws IOException { //创建套接字 Socket socket=new Socket(InetAddress.getLocalHost(),9999); System.out.println("客户端获取套接字成功"); //获取输出流,发送数据及结束标识 BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); bufferedWriter.write("hello, server"); bufferedWriter.flush(); socket.shutdownOutput(); System.out.println("客户端发送数据结束"); //获取连接输入流,读取数据并打印 String str; BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream())); while((str=bufferedReader.readLine())!=null){ System.out.println(str); } System.out.println("读取数据结束"); //关闭流与套接字 bufferedWriter.close(); bufferedReader.close(); socket.close(); System.out.println("客户端已关闭流及连接"); } }
TCP文件传输案例
服务端
package socket; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.nio.file.Files; import java.nio.file.Paths; /** * (1)编写客户端程序和服务器端程序 * (2)客户端可以传输一个图片文件名给服务端,比如奥迪.jpg, * (3)服务端收到图片名后,从D:\temp\source读取对应图片文件,并客户端返回这个图片文件,如果服务器没有这个文件,返回一个默认的图片即可。 * (3)客户端收到文件后,保存到本地D:\temp\target\ * * 运行提示: * 1. 创建好D:\temp\target\和D:\temp\source这两个文件夹 * 2. 在D:\temp\source中存储一张"奥迪.jpg"和“无名.jpg” */ public class SocketTCPFileTestServer { //源文件目录路径 private static final String SOURCE_FOLDER_PATH="D:\\temp\\source\\"; public static void main(String[] args) throws IOException { //1.创建socket服务器对象,并获取连接 ServerSocket serverSocket=new ServerSocket(9999); System.out.println("等待客户端连接..."); Socket socket=serverSocket.accept(); System.out.println("获取来自客户端的连接:"+socket.getInetAddress()); //2.获取接收到的文件名 InputStreamReader inputStreamReader=new InputStreamReader(socket.getInputStream()); StringBuilder stringBuilder= new StringBuilder(); char[] chars=new char[32]; int len=0; while((len=inputStreamReader.read(chars))!=-1){ stringBuilder.append(new String(chars,0,len)); } String fileName=stringBuilder.toString(); System.out.println("获取文件名完成:"+fileName); //3.判断要获取的文件名,如果不是奥迪.jpg,就传输无名.jpg if(!"奥迪.jpg".equals(fileName)){ fileName="无名.jpg"; } //4.读取本地的图片,并发送给客户端 String filePath=SOURCE_FOLDER_PATH+fileName; BufferedInputStream bufferedInputStream=new BufferedInputStream(Files.newInputStream(Paths.get(filePath))); BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(socket.getOutputStream()); byte[] bytes=new byte[1024]; while(bufferedInputStream.read(bytes)!=-1){ bufferedOutputStream.write(bytes); } bufferedOutputStream.flush();//清除缓存,确认发送 socket.shutdownOutput();//发送传输结束标志 System.out.println("读取本地图片并发送给客户端完成"); //4.关闭连接 inputStreamReader.close(); bufferedInputStream.close(); bufferedOutputStream.close(); socket.close(); System.out.println("关闭来自"+socket.getInetAddress()+"的连接"); } }
客户端
package socket; import java.io.*; import java.net.InetAddress; import java.net.Socket; import java.nio.file.Files; import java.nio.file.Paths; /** * (1)编写客户端程序和服务器端程序 * (2)客户端可以传输一个图片文件名给服务端,比如奥迪.jpg, * (3)服务端收到图片名后,从D:\temp\source读取对应图片文件,并客户端返回这个图片文件,如果服务器没有这个文件,返回一个默认的图片即可。 * (3)客户端收到文件后,保存到本地D:\temp\target\ * * 运行提示: * 1. 创建好D:\temp\target\和D:\temp\source这两个文件夹 * 2. 在D:\temp\source中存储一张"奥迪.jpg"和“无名.jpg” */ public class SocketTCPFileTestClient { //目标文件目录路径 private static final String TARGET_FOLDER_PATH="D:\\temp\\target\\"; public static void main(String[] args) throws IOException { //1. 与服务器建立链接 Socket socket=new Socket(InetAddress.getLocalHost(),9999); System.out.println("客户端已获取和服务器的链接"); //2.向服务器发送文件名奥迪.jpg String fileName="奥迪.jpg"; OutputStreamWriter outputStreamWriter=new OutputStreamWriter(socket.getOutputStream()); outputStreamWriter.write(fileName); outputStreamWriter.flush();//清除缓存,确认发送 socket.shutdownOutput();//发送结束传输标志 System.out.println("客户端已发送文件名:"+fileName); //3. 接收服务器发送的图片并保存到目标文件目录 BufferedInputStream bufferedInputStream=new BufferedInputStream(socket.getInputStream()); BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(Files.newOutputStream(Paths.get(TARGET_FOLDER_PATH+fileName))); byte[] bytes=new byte[1024]; while(bufferedInputStream.read(bytes)!=-1){ bufferedOutputStream.write(bytes); } System.out.println("客户端接收文件完成"); //4. 关闭连接 outputStreamWriter.close(); bufferedInputStream.close(); bufferedOutputStream.close(); socket.close(); System.out.println("客户端已关闭连接"); } }