套接字Socket
socket是操作系统的接口, 屏蔽了TCP/IP协议的通信细节,使得程序员无需关注协议本身,直接使用socket提供的接口来进行互联的不同主机间的进程的通信
起源于 UNIX BSD
unix中万物皆文件,bsd在实现上把socket设计成一种文件,然后通过虚拟文件系统的操作接口就可以访问socket,而访问socket时会调用相应的驱动程序,从而也就是使用底层协议进行通信。
socket是"打开—读/写—关闭"模式的实现,以使用TCP协议通讯的socket为例,其交互流程大概如下:
TCP为例socket通信流程
Java 对网络支持的4大类
InetAddress
表示IP地址
public class Test01 {
public static void main(String[] args) throws UnknownHostException {
// 获取本机的InetAddress实例
InetAddress address = InetAddress.getLocalHost();
System.out.println("计算名:" + address.getHostName());
System.out.println("IP地址:" + address.getHostAddress());
byte[] bytes = address.getAddress();// 获取字节数组形式的IP地址
System.out.println("字节数组形式的IP:" + Arrays.toString(bytes));
System.out.println(address);// 直接输出InetAddress对象
// 根据机器名获取InetAddress实例
// InetAddress address2=InetAddress.getByName("laurenyang");
InetAddress address2 = InetAddress.getByName("1.1.1.10");
System.out.println("计算名:" + address2.getHostName());
System.out.println("IP地址:" + address2.getHostAddress());
}
}
URL
public class Test02 {
public static void main(String[] args) {
try {
//创建一个URL实例
URL imooc=new URL("http://www.imooc.com");
//?后面表示参数,#后面表示锚点
URL url=new URL(imooc, "/index.html?username=tom#test");
System.out.println("协议:"+url.getProtocol());//http
System.out.println("主机:"+url.getHost());//www.imooc.com
//如果未指定端口号,则使用默认的端口号,此时getPort()方法返回值为-1
System.out.println("端口:"+url.getPort());//-1
System.out.println("文件路径:"+url.getPath());///index.html
System.out.println("文件名:"+url.getFile());//index.html?username=tom
System.out.println("相对路径:"+url.getRef());//test 锚点
System.out.println("查询字符串:"+url.getQuery());//username=tom
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
Socket
服务端先启动 指定监听的端口8888 堵在accept()
public class Server {
public static void main(String[] args) {
try {
//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
ServerSocket serverSocket=new ServerSocket(8888);
//2.调用accept()方法开始监听,等待客户端的连接
Socket socket=serverSocket.accept();//堵塞
//3 .获取输入流 读取客户信息
InputStream is=socket.getInputStream();
InputStreamReader isr=new InputStreamReader(is);;
BufferedReader br= new BufferedReader(isr);;
String info;
while((info=br.readLine())!=null){
InetAddress address=socket.getInetAddress();
System.out.println("当前客户端的IP:"+address.getHostAddress());
System.out.println("来自客户端信息:"+info);
}
//关闭
socket.shutdownInput();
br.close();
isr.close();
is.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端向其(ip+端口)发数据
public class Client {
public static void main(String[] args) {
try {
//1.创建客户端Socket,指定服务器地址和端口
Socket socket=new Socket("localhost", 8888);
//2.获取输出流,向服务器端发送信息
OutputStream os=socket.getOutputStream();//字节输出流
PrintWriter pw=new PrintWriter(os);//将输出流包装为打印流
pw.write("用户名:alice;密码:789");
pw.flush();
socket.shutdownOutput();//关闭输出流
//4.关闭资源
pw.close();
os.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UDP
无连接,不可靠,无序,但是快
以数据报Datagram作为数据传输的载体
DatagramPacket 数据报包(数据单位)
DatagramSocket端到端通信的类
先启动服务端
DatagramSocket里面有端口号
用数组创建一个DatagramPacket
用DatagramSocket把数据接收到DatagramPacket
这样数据就在数组里面了
端口后8800 堵在receive(packet)
public class UDPServer {
public static void main(String[] args) throws IOException {
//1.创建服务器端DatagramSocket,指定端口
DatagramSocket socket=new DatagramSocket(8800);
//2.创建数据报,用于接收客户端发送的数据
byte[] data =new byte[1024];//创建字节数组,指定接收的数据包的大小
DatagramPacket packet=new DatagramPacket(data, data.length);
//3.接收客户端发送的数据
socket.receive(packet);//此方法在接收到数据报之前会一直阻塞
//4.读取到数据
String info=new String(data, 0, packet.getLength());
}
}
数据报包DatagramPacket里面的目的地ip,端口 和要发的byte[]
把DatagramPacket放入DatagramSocket发送
public class UDPClient {
public static void main(String[] args) throws IOException {
//要发送的数据
byte[] data="用户名:admin;密码:123".getBytes();
//要发的IP地址
InetAddress address=InetAddress.getByName("localhost");
//1.数据报
DatagramPacket packet=new DatagramPacket(data, data.length, address, 8800);
//2.DatagramSocket
DatagramSocket socket=new DatagramSocket();
//4.发送
socket.send(packet);
socket.close();
}
}