目录
前言
- Java是Internet上的语言,它从语言级上提供了对网络应用程序的支持,程序员能够很容易开发常见的网络应用程序。
- Java提供的网络类库,可以实现无痛的网络连接,联网的底层细节被隐藏在Java的本机安装系统里,由JVM进行控制。并且Java实现了一个跨平台的网络库,程序员面对的是一个统一的网络编程环境。
计算机网络:
- 把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息、共享硬件、软件、数据信息等资源。
网络编程的目的:
- 直接或间接地通过网络协议与其它计算机实现数据交换,进行通讯。
网络编程中有两个主要的问题:
- 如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
解决方法:提供IP和端口号
- 找到主机后如何可靠高效地进行数据传输
解决方法:提供网络通信协议:TCP/IP参考模型
一、网络通信要素
1.通信双方地址
①IP
用于识别主机
②端口号
0-65535之间
公共端口:0-1023,被预先定义的服务通信占用(如HTTP占用短裤80,FTP占用端口21,Telnet占用端口23)
注册端口:1024-49151,分配个给用户进程或应用程序(如:Tomcat占用端口8080,MySQL占用端口3306,Oracle占用端口1521等)
动态/私有端口:49152-65535
用于识别正在计算机上运行的进程(程序)
2.规则(网络通信协议,有两套参考模型)
①OSI参考模型:模型过于理想化,未能在因特网上进行广泛推广
②TCP/IP参考模型(或TCP/IP协议):事实上的国际标准
二、InetAddress
在Java中使用InetAddress类代表IP
①构造方法
构造器私有化,无法直接构造
②常用方法
1.getByName(String host) //根据主机名或域名,返回InetAddress对象
本地回路地址:127.0.0.1或localhost
2.getLocalHos() //获取本地IP
3.getHostAddress() //获取此IP地址
4.getHostName() //获取此IP的主机名
三、TCP与UDP通信协议
1.TCP:传输控制协议
- 使用TCP协议前,须先建立TCP连接,形成传输数据通道
- 传输前,采用“三次握手”方式,点对点通信,是可靠的
- TCP协议进行通信的两个应用进程:客户端、服务端
- 在连接中可进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低
2.UDP:用户数据协议
- 将数据、源、目的封装成数据包,不需要建立连接
- 每个数据报的大小限制在64K内
- 发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
- 可以广播发送
- 发送数据结束时无需释放资源,开销小,速度快
四、TCP网络通信编程
1.基本流程
①通过端口号创建服务端(ServerSocket)
②客户端通过IP和端口连接上服务端(Socket)
③进行通信
2.服务端:ServerSocket
①构造方法
new ServerSocket(int port); //创建绑定到特定端口的服务器套接字。
②常用方法
1.accept() //侦听并接受到此套接字的连接,返回Socket对象,如果没客户端连接就一直阻塞
3.Socket
①构造方法
new Socket(InetAddress address, int port) //创建一个流套接字并将其连接到指定 IP 地址的指定端口号
②常用方法
1.getInputStream() //返回此套接字的输入流
2.getOutputStream() //返回此套接字的输出流
3.shutdownOutput() //表示输出结束
4.shutdownInput() //表示输入结束
4.TCP网络编程案例
服务端给客户端发“hello,client”,客户端给服务端发“hello,server”
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class SocketTCP03Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("连接服务端成功");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write("hello,sever");
bufferedWriter.newLine();
bufferedWriter.flush();
String readData;
while((readData = bufferedReader.readLine()) != null){
System.out.println(readData);
}
bufferedReader.close();
bufferedWriter.close();
socket.close();
System.out.println("客户端退出");
}
}
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketTCP03Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("等待客户端连接");
Socket socket = serverSocket.accept();
System.out.println("连接客户端成功");
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write("hello,client");
bufferedWriter.newLine();
bufferedWriter.flush();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String readData = bufferedReader.readLine();
System.out.println(readData);
bufferedReader.close();
bufferedWriter.close();
socket.close();
System.out.println("服务端退出");
}
}
五、UDP网络通信编程
- 没有明确的服务端和客户端,演变成数据的发送端和接收端,而且这两个角色可以随时转变
- 类DatagramSocket和DatagramPacket(数据包/数据包)实现了基于UDP协议网络程序
- UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不确定什么时候可以抵达
- DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号
- UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
1.基本流程
①创建核心的两个类对象 DatagramSocket和DatagramPacket
②建立发送端,接收端
③建立数据包
④调用DatagramSocket的发送,接收方法
⑤关闭DatagramSocket
2.DatagramSocket
①构造方法
new DatagramSocket(int port) //创建数据报套接字并将其绑定到本地主机上的指定端口
new DatagramSocket(SocketAddress bindaddr) // 创建数据报套接字,将其绑定到指定的本地套接字
// 地址
new DatagramSocket(int port, InetAddress laddr) // 创建数据报套接字,将其绑定到指定的本地地
// 址
②常用方法
1.send(DatagramPacket p) //从此套接字发送数据报包
2.receive(DatagramPacket p) //从此套接字接收数据报包
3.close() //关闭此数据报套接字
3.DatagramPacket
①构造方法
//构造 DatagramPacket,用来接收长度为 length的数据包
new DatagramPacket(byte[] buf, int length)
//构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号
new DatagramPacket(byte[] buf, int length, InetAddress address, int port)
②常用方法
1.getData() //返回数据缓冲区
2.getLength() //返回将要发送或接收到的数据的长度
4.UDP网络编程案例
建立一个接收端A一个发送端B,B给A说:“hello,明天吃火锅”,B回复A说:“明天见”
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPReceiverA {
public static void main(String[] args) throws IOException {
//接收端A,收到信息后回复好的,明天见
//1.创建一个DatagramSocket对象,准备在端口9999等待接收数据
DatagramSocket datagramSocket = new DatagramSocket(9999);
//2.创建一个DatagramPacket对象,准备接收数据
byte[] buf = new byte[64*1024];
DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);
//3.调用receive接收方法,将通过网络传输的DatagramPacket对象填充到packet对象
//如果没有接收到数据包会阻塞等待
datagramSocket.receive(datagramPacket);
//4.把packet进行拆包,取出数据并显示
int length = datagramPacket.getLength();
byte[] data = datagramPacket.getData();
System.out.println(new String(data,0,length));
//创建DatagramPacket对象用于发送数据
byte[] fasong = "明天见".getBytes();
DatagramPacket datagramPacket1 = new DatagramPacket(fasong, fasong.length, InetAddress.getLocalHost(), 9998);
//调用发送方法
datagramSocket.send(datagramPacket1);
//关闭资源
datagramSocket.close();
}
}
import java.io.IOException;
import java.net.*;
public class UDPSenderB {
public static void main(String[] args) throws IOException {
//发送端B,给接收端A发信息:hello,明天吃火锅~
//1.创建一个DatagramSocket对象,准备发送和接收数据
DatagramSocket datagramSocket = new DatagramSocket(9998);
//2.创建一个DatagramPacket对象,填好IP和端口准备给其发送信息
byte[] buf = "hello,明天吃火锅~".getBytes();
DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 9999);
//调用send发送方法,将DatagramPacket数据包发送给接收方
datagramSocket.send(datagramPacket);
//创建一个DatagramPacket对象用于接收数据
byte[] data = new byte[1024*64];
DatagramPacket datagramPacket1 = new DatagramPacket(data, data.length);
//调用接收方法
datagramSocket.receive(datagramPacket1);
//拆包
int length = datagramPacket1.getLength();
byte[] data1 = datagramPacket1.getData();
System.out.println(new String(data1,0,length));
//关闭资源
datagramSocket.close();
}
}