基本概念
IP:对应着网络中唯一的主机
端口号: 端口号用来标识正在计算机上运行的进程(程序),范围是0~65535
InetAddress类
This class represents an Internet Protocol (IP) address.在Java中,使用InetAdress类来表示一个IP地址。
InetAddress类构造器私有化了,需要通过getByName(String host)、getLocalHost()来实例化对象。
常用的方法有getHostName()、getHostAddress();
public class InetDemo {
public static void main(String[] args){
try {
/*
类似于File file = new File("hello.txt");
InetAddress对象对应着一个具体的IP地址的值
缺点,通过IP地址访问,不太容易记忆
*/
InetAddress inet1 = InetAddress.getByName("192.168.10.11");
System.out.println(inet1);
/*
通过域名访问,方便记忆
*/
InetAddress inet2 = InetAddress.getByName("www.baidu.com");
System.out.println(inet2);
/*
本地回路地址:127.0.0.1 对应着localhost(本机)
*/
InetAddress inet3 = InetAddress.getByName("localhost");
System.out.println(inet3);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
网络通信协议
TCP和UDP
TCP协议
1、使用TCP协议前, 需先建立TCP连接,形成传输数据通道。
2、传输前,采用**“三次握手”**方式,点对点通信,是可靠的
3、TCP协议进行通信的两个应用进程:客户端、服务端
4、在连接中可进行大数据量的传输
5、传输完毕,需释放已建立的连接,效率低
UDP协议
1、将数据、源、目的封装成数据包,不需要建立拦截。
2、每个数据报的大小限制在64kb
3、发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
4、可以广播发送
5、发送数据结束时无序释放资源,开销小,速度快
TCP/IP
案例一:通过TCP实现服务端与客户端通信
客户端:
package com.inet.demo5;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
Socket socket = null;
OutputStream out = null;
try {
//1、创建一个socket对象,指明服务器端的ip和端口号
socket = new Socket("127.0.0.1", 6666);
//2、获取一个输出流,用于输出数据
out = socket.getOutputStream();
//写数据
out.write("你好,服务端!".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {//关闭资源
try {
if (out != null) {
out.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务器端:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
ServerSocket ss = null;
Socket socket = null;
InputStream in = null;
ByteArrayOutputStream out = null;
try {
ss = new ServerSocket(6666);
socket = ss.accept();
in = socket.getInputStream();
/*
不建议采用这种写法,如果byte数组给的小,则一次性读不完,会乱码
byte[] b = new byte[1024];
int len ;
while ((len = in.read(b)) != -1) {
String str = new String(b,0,len);
System.out.print(str);
}
*/
//这样先把数据读到byte数组中去,整体读完才去转换成字符串,不会乱码
out = new ByteArrayOutputStream();
byte[] b = new byte[5];
int len;
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
System.out.println(out.toString());
System.out.println("收到了来自"+socket.getInetAddress().getHostAddress()+"的消息");
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源 为了保证资源关闭必须执行,所以要用try-catch-finally来执行,不能通过throws来抛出
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
if (socket != null) {
socket.close();
}
if (ss != null) {
ss.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
案例二:实现客户端向服务器端发送文件,服务器向客户端返回 “接收成功信息” 在客户端打印输出
客户端
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
Socket socket = null;
OutputStream out = null;
FileInputStream fis = null;
InputStream in = null;
ByteArrayOutputStream bos = null;
try {
//1、创建一个socket对象,指明ip和端口
socket = new Socket(InetAddress.getByName("127.0.0.1"), 6666);
//2、获取输出流
out = socket.getOutputStream();
//3、从外部读取文件
fis = new FileInputStream("D:\\1.mp4");
byte[] b = new byte[1024];
int len;
while ((len = fis.read(b)) != -1) {
out.write(b, 0, len);
}
//4、在这里关闭数据的输出,服务端就得到了明确的指示,不会阻塞等待
socket.shutdownOutput();
//5、获取输入流
in = socket.getInputStream();
//6、读取服务端返回的数据
bos = new ByteArrayOutputStream();
byte[] b1 = new byte[1024];
int length;
while ((length = in.read(b1)) != -1) {
bos.write(b1, 0, length);
}
System.out.println(bos.toString());
} catch (IOException e) {
e.printStackTrace();
} finally { //7、关闭资源
try {
if (bos != null) {
bos.close();
}
if (in != null) {
in.close();
}
if (fis != null) {
fis.close();
}
if (out != null) {
out.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务器端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
ServerSocket ss = null;
Socket socket = null;
InputStream in = null;
FileOutputStream fos = null;
OutputStream out = null;
try {
//1、创建服务器端的ServerSocket,指明自己的端口号
ss = new ServerSocket(6666);
//2、调用accept()表示接收来自于客户端的socket
socket = ss.accept();
//3、获取输入流
in = socket.getInputStream();
//4、将客户端传来的文件保存到本地
fos = new FileOutputStream("D:\\temp\\2.mp4");
byte[] b = new byte[1024];
int len;
/*
重点注意! read()方法是一个阻塞式的方法
意思就是你没有告诉我结束的时候,我就不会停止循环
当读完一个文件时,它还是会继续阻塞,等待客户端给它发送数据
因为客户端并没有给一个明确的指示说传送完毕
所以服务器端还停留在while循环当中,就会阻塞在这
下面的语句也就不会执行
*/
while ((len = in.read(b)) != -1) {
fos.write(b, 0, len);
}
System.out.println("视频传输完成");
//5、获取输出流
out = socket.getOutputStream();
if (in.read(b) == -1) {//如果文件读取完毕,则返回接收成功
out.write("接收成功".getBytes());
}
} catch (IOException e) {
e.printStackTrace();
} finally { //关闭资源
try {
if (out != null) {
out.close();
}
if (fos != null) {
fos.close();
}
if (in != null) {
in.close();
}
if (socket != null) {
socket.close();
}
if (ss != null) {
ss.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
UDP
类DatagramSocket和DatagramPacket实现了基于UDP协议网络程序。
UDP数据包通过数据包套接字DatagramSocket来接收,而DatagramPacket对象封装了UDP数据包,在数据包中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。UDP协议中每个数据包都给出了完整的地址信息,不需要建立连接,所以不可靠,但是速度快,高效。
具体流程
1、建立发送端,接收端
2、建立数据包
3、调用Socket的发送、接收方法
4、关闭Socket
UDP通信案例
发送端
package com.inet.udpdemo;
import java.io.IOException;
import java.net.*;
public class Send {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket();//不需要在socket中填数据
String str = "来自发送端的数据";
byte[] data = str.getBytes();//转为byte数组
InetAddress inet = InetAddress.getLocalHost();//获取一个InetAddress对象,指明ip地址
DatagramPacket packet = new DatagramPacket(data,0,data.length,inet,6666);
socket.send(packet);
socket.close();
}
}
接收端
package com.inet.udpdemo;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Receive {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(6666);//指定端口号
byte[] b = new byte[1024];//定义一个byte数组来存放接收的数据
DatagramPacket packet = new DatagramPacket(b,0,b.length);//读取byte数组中的数据保存到数据包中
socket.receive(packet);//接收数据包
System.out.println(new String(packet.getData(),0,packet.getLength()));//读取packet中的数据
socket.close();
}
}
URL
Uniform Resource Locator 统一资源定位符,它代表Internet上某一资源的地址
URL的五个基本组成部分:
<传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表
片段名:即锚点,例如看小说,直接定位到章节
参数列表格式:参数名=参数值&参数名=参数值…
URL的一些基本操作
package com.inet;
import java.net.MalformedURLException;
import java.net.URL;
public class URLDemo {
public static void main(String[] args) {
try {
URL url = new URL("https://www.baidu.com/s?cl=3&tn=baidutop10&fr=top1000&wd=31%E7%9C%81%E6%96%B0%E5%A2%9E%E6%9C%AC%E5%9C%9F%E7%A1%AE%E8%AF%8A93%E4%BE%8B%3A%E6%B2%B3%E5%8C%9754%E4%BE%8B&rsv_idx=2&rsv_dl=fyb_n_homepage&hisfilter=1");
System.out.println(url.getProtocol());//获取该URL的协议名
System.out.println(url.getHost());//获取该URL的主机名
System.out.println(url.getPort());//获取该URL的端口号
System.out.println(url.getPath());//获取该URL的文件路径
System.out.println(url.getFile());//获取该URL的文件名
System.out.println(url.getQuery());//获取该URL的查询名
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
案例:从网上下载图片
package com.inet.url;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* 从网络下载文件
*/
public class URLDemo2 {
public static void main(String[] args) {
HttpURLConnection urlConnection = null;
InputStream in = null;
FileOutputStream fos = null;
try {
//填入下载图片所在url
URL url = new URL("https://pics6.baidu.com/feed/a044ad345982b2b76c7e400d4fde22e874099b95.jpeg?token=484a6fd24eae05e83005e65a6e7e045f&s=6D428B46A88BA55594F44D9303008083");
urlConnection = (HttpURLConnection) url.openConnection();//获取服务器连接,用的是http协议,所以获得的是HttpURLConnection
urlConnection.connect();//访问服务器
in = urlConnection.getInputStream();
fos = new FileOutputStream("D:\\cc.png");
byte[] b = new byte[1024];
int len;
while ((len = in.read(b)) != -1) {
fos.write(b, 0, len);
}
System.out.println("下载完毕");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
}