JavaEE - 14网络编程
(1)网络编程概述
- Java是Internet上的语言,从语言级上提供了对网络应用程序的支持,能够很容易开发常见的网络应用程序。
- Java提供的网络类库,可以实现网络连接,联网的底层细节被隐藏在Java的本机安装系统里,由JVM进行控制。
- 并且Java实现了一个跨平台的网络库。程序员面对的是一个统一的网络编程环境。
- 计算机网络:把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统,
- 从而使众多的计算机可以方便地互相传递消息、共享硬件、软件、数据信息等资源。
- 网络编程的目的:直接或间接地通过网络协议与其它计算机实现数据交换,进行通讯。
- 网络编程的主要问题:
- 如何准确地定位网络中一台或多台主机;定位主机上的特定的应用
- 找到主机后如何可靠高效地进行数据传输
(2)网络通信要素
- IP和端口号
- 网络通信协议 OSI参考模型 TCP/IP参考模型
- 各层协议: HTTP、FTP、Telnet、DNS... TCP、UDP、... IP、ICMP、ARP...
- 数据封装 <--> 数据拆封
(3)IP和端口号
- 唯一的标识Internet上的计算机(通信实体)
- 本地回环地址: 127.0.0.1, 主机名: localhost
- IP地址分类方式1: IPV4(4个字节组成) 和IPV6(16个字节,8个无符号整数,每个整数用四个16进制标识,冒号分隔)
- IP地址分类方式2: 公网地址 和 私有地址。
- 端口号: 0~65535。 公认端口0~1023。 注册端口 1024~49151。 动态/私有端口49152~65535
- 端口号与IP地址的组合得到一个网络套接字:Socket。
InetAddress实例化: 两个方法: getByName(String host)、 getLocalHost(); 常用方法: inet1.getHostAddress() / inet1.getHostName()
@Test public void test1() throws UnknownHostException { InetAddress inet1 = InetAddress.getByName("192.168.0.32"); InetAddress inet2 = InetAddress.getByName("www.share1949.com"); InetAddress inet3 = InetAddress.getByName("127.0.0.1"); InetAddress inet4 = InetAddress.getLocalHost(); System.out.println(inet1); // /192.168.0.32 System.out.println(inet2); // www.share1949.com/27.223.104.55 System.out.println(inet3); // /127.0.0.1 System.out.println(inet4); // SC-202003181202/192.168.0.126 }
(4)网络通信协议
- 传输控制协议TCP(Transmission Control Protocol)
- 使用TCP协议之前,先建立TCP连接,形成传输数据通道
- 传输前,采用"三次握手"方式,点对点通信,是可靠的
- TCP协议进行通信的两个应用进程: 客户端、服务端
- 在连接中进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低
- TCP三次握手 、TCP四次挥手
- 用户数据报协议UDP(User Datagram Protocol)
- 将数据、源、目的 封装成数据包,不需要建立连接
- 每个数据报的大小限制在64K内
- 发送不管对方是否准备好,接收方收到也不确认,是不可靠的
- 可以广播发送
- 发送数据结束时无需释放资源,开销小,速度快
(5)TCP网络编程
server服务端程序
@Test public void server() throws IOException { ServerSocket ss = new ServerSocket(8899); Socket socket = ss.accept(); InputStream is = socket.getInputStream(); // 存在乱码的可能 // byte[] buffer = new byte[20]; // int len; // while((len = is.read(buffer)) != -1){ // String str = new String(buffer, 0, len); // System.out.println(str); // } ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[5]; int len; while ((len = is.read(buffer)) != -1){ baos.write(buffer,0,len); } System.out.println("收到了来自于:" + socket.getInetAddress().getHostAddress() + "的消息" );
System.out.println(baos.toString()); // 您好,我是客户端
baos.close();
is.close();
socket.close();
ss.close();
}
client客户端程序
@Test public void client(){ Socket socket = null; OutputStream os = null; try{ InetAddress inet = InetAddress.getByName("127.0.0.1"); socket = new Socket(inet, 8899); os = socket.getOutputStream(); os.write("您好,我是客户端".getBytes()); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if(os != null){ try{ os.close(); } catch (IOException e) { e.printStackTrace(); } } } }
客户端往服务端传输图片文件,数据传输完成后,服务端发送消息给客户端,客户端打印在控制台
@Test public void server() throws IOException { ServerSocket ss = new ServerSocket(9090); Socket socket = ss.accept(); InputStream is = socket.getInputStream(); FileOutputStream fos = new FileOutputStream(new File("beauty.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(); ss.close();
os.close(); } @Test public void client() throws IOException { Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090); OutputStream os = socket.getOutputStream(); FileInputStream fis = new FileInputStream(new File("22.jpg")); byte[] buff = new byte[1024]; int len; while ((len = fis.read(buff)) != -1){ os.write(buff,0,len); } // 数据传输完成后,关闭输出 socket.shutdownOutput(); // 接收服务端给的响应,并打印到控制台 InputStream is = socket.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer3 = new byte[10]; int len3; while((len3 = is.read(buffer3)) != -1){ baos.write(buffer3,0,len3); } System.out.println(baos.toString()); }
(6)UDP网络编程
- DatagramSocket和DatagramPacket 类实现了基于UDP协议网络程序。
- UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够送达目的地,也不能确定什么时候抵达。
- DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
- UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接。
@Test public void sender() throws IOException { DatagramSocket socket = new DatagramSocket(); String str = "UDP方式发送的消息"; byte[] data = str.getBytes(); InetAddress inet = InetAddress.getLocalHost(); DatagramPacket packet = new DatagramPacket(data, 0,data.length,inet,9090); socket.send(packet); socket.close(); } @Test public void receiver() throws IOException { DatagramSocket socket = new DatagramSocket(9090); byte[] buffer = new byte[10]; DatagramPacket packet = new DatagramPacket(buffer, 0,buffer.length); socket.receive(packet); String str = new String(packet.getData(),0,packet.getLength()); System.out.println(str); socket.close(); }
(7)URL编程
- URL(Uniform Resource Locator): 统一资源定位符,表示Internet上某一资源的地址。
- URL是一种具体的URI, URL可以用来标识一个资源,还指明了如何locate这个资源。
- 通过URL可以访问Internet上的网络资源,如www、ftp。浏览器通过解析给定的URL在网络上查找相应的文件或其他资源。
- URL的结构: <传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表
- http://192.168.0.100:8080/helloworld/index.jsp#a?username=sun&password=123
@Test public void test1() throws MalformedURLException { URL url = new URL("http://192.168.0.100:8080/helloworld/index.jsp#a?username=sun&password=123"); System.out.println(url.getProtocol()); // 协议名: http System.out.println(url.getHost()); // 主机名: 192.168.0.100 System.out.println(url.getPort()); // 端口号: 8080 System.out.println(url.getPath()); // 文件路径: /helloworld/index.jsp System.out.println(url.getFile()); // 文件名: /helloworld/index.jsp System.out.println(url.getQuery()); // 查询名: null }
@Test public void test2() throws IOException { URL url = new URL("https://timgsa.baidu.com/timg?image&quality=F59%2F19300001325156131228593878903.jpg"); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.connect(); InputStream is = urlConnection.getInputStream(); FileOutputStream fos = new FileOutputStream("logo.jpg"); byte[] buffer = new byte[1024]; int len; while((len = is.read(buffer)) != -1){ fos.write(buffer,0,len); } is.close(); fos.close(); urlConnection.disconnect(); }