1.网络的概述:
协议:
在网络之间传出数据是需要按照指定的标准来传输,标准中规定数据的格式,大小,传输的方式,传输的速率;
标准写在文件中形成一个统一的规范-->按照规范开发的代码->协议;
网络:
应用层:我们开发的程序在这一层;
传输层:在这一层指定了使用什么格式,对要发送的数据进行分包和发送;
网络层:在这一层,会对目标IP地址进行校验
链路层:包含了网卡及其驱动程序
IP地址:互联网协议地址
格式: 数字.数字.数字.数字 数字在0-255之间;
通常说的IP地址是指外网的IP地址;
内网中的IP都是以192开头的。
作用:用来唯一标识互联网中某一台电脑的地址的,通过IP地址就可以找到对应的电脑;
端口号:
就是一个数字,范围1-65536,这个数字是用来唯一标识一个安装在你的电脑上的软件。
1024之前的端口是系统保留的端口;1024之后的可以让开发人员来使用。
常见的端口:
tomcat:8080
http:80
mysql:3306
作用:用来唯一标识一个安装在你的电脑上的软件。
要想给对方发送数据,需要指定发送数据和对方的IP与端口;
是用来封装 网络地址;
网络地址:ip地址,端口号,主机名称;
常用方法:
public class Example01 {
public static void main(String[] args) throws Exception {
InetAddress local = InetAddress.getLocalHost();
InetAddress remote = InetAddress.getByName("www.itcast.cn");
System.out.println("本机的IP地址:" + local.getHostAddress());
System.out.println("itcast的IP地址:" + remote.getHostAddress());
System.out.println("itcast的主机名为:" + remote.getHostName());
}
}
UDP称为用户数据报协议;
特点:
1.发送端只发送数据,不管接收端是否接收数据或者数据接收是否完整;
2.接收端只管接收数据;
3.允许发送的数据出现丢失的现象;
应用场景:
视频直播;
广播;
TCP称为传输控制协议;
特点:
1.客户端:发送数据;
2.服务器端:接收数据;
3.不允许出现数据丢失的情况;
应用场景:
上传下载文件;
1.发送端程序
步骤:
1.创建DatagramSocket对象,作为一个发送端,就相当于一个码头;
2.创建一个DatagramPacket对象,用于封装要发送的数据,就相当于一个集装箱;
3.调用DatagramSocket 对象的send方法,发送数据报;
4.关闭DatagramSocket对象,就相当于关闭码头;
示例代码:
public class Sender{
public static void main(String[] args)throws Exception{
//1.创建DatagramSocket对象,作为一个发送端,就相当于一个码头;
DatagramSocket s=new DatagramSocket();
//2.创建一个DatagramPacket对象,用于封装要发送的数据,就相当于一个集装箱;
byte[] data="今晚7点操场西北角小树林不见不散!”.getBytes();
DatagramPacket dp=new DatagramPacket(data,data.length,InetAddress.getByName("192.168.186.50"),6000);
//3.调用DatagramSocket对象send方法,发送数据报;
s.send(dp);
//4.关闭DatagramSocket对象,就相当于关闭码头;
s.close();
}
}
2.接收端
步骤:
1.创建DatagramSocket对象,作为一个发送端,相当于一个码头;
2.创建一个DatagramPacket对象,用于封装接收的数据,就相当于一个集装箱;
3.调用DatagramSocket对象的receive方法接收数据;
4.得到接收的数据;
5.展示数据;
6.关闭DatagramPacket对象;
示例代码:
public class Receiver{
public static void main(String[] args)throws Exception{
//1.创建DatagramSocket对象,作为一个发送端,相当于一个码头;
DatagramSocket s=new DatagramSocket(6000);
//2.创建一个DatagramPacket对象,用于封装接收的数据,就相当于一个集装箱;
byte[] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,1024);
//3.调用DatagramSocket对象的receive方法接收数据;
s.receive(dp);
//4.得到接收的数据;
byte[] data=dp.getDate();
//5.展示数据;
System.out.println(new String(data);
//6.关闭DatagramPacket对象;
s.close();
}
}
1.客户端程序
步骤:
// 1.创建一个Socket对象,作为客户端;
// 2.通过Socket对象得到输出流,用于把要发送的数据写到服务器端;
// 3.使用输出流写数据(发送数据);
// 4.告诉服务器端发送已经完成;
// 5.展示数据;
// 6.关闭流,关闭Socket;
示例代码:
public class Client {
public static void main(String[] args) throws Exception {
// 1.创建一个Socket对象,作为客户端;
Socket s = new Socket("192.168.186.50", 6000);
// 2.通过Socket对象得到输出流,用于把要发送的数据写到服务器端;
OutputStream out = s.getOutputStream();
// 3.使用输出流写数据(发送数据);
out.write("今晚7点操作西北角小树林不见散!".getBytes());
// 4.告诉服务器端发送已经完成;
s.shutdownOutput();
//----接收服务器端发送的数据--------------------
InputStream in = s.getInputStream();
int len = -1;
byte[] bArray = new byte[1024];
while((len=in.read(bArray)) != -1){
// 5.展示数据;
System.out.println(new String(bArray,0,len));
}
in.close();
// 6.关闭流,关闭Socket;
s.close();
}
}
2.服务器端程序
步骤:
// 1.创建一个ServerSocket对象,作为服务器端;
// 2.调用ServerSocket对象的accept方法,接收数据,返回的是Socket对象,它对应了客户端对象
// 3.通过Socket对象得到一个输入流(客户端发送数据使用的那个输出流);
// 4.通过输入流得到客户端发送的数据;
// 5.展示数据;
// 6.关闭流,socket和ServerSocket对象;
示例代码:
public class Server {
public static void main(String[] args) throws Exception {
// 1.创建一个ServerSocket对象,作为服务器端;
ServerSocket ss = new ServerSocket(6000);
// 2.调用ServerSocket对象的accept方法,接收数据,返回的是Socket对象,它对应了客户端对象
Socket s = ss.accept();
// 3.通过Socket对象得到一个输入流(客户端发送数据使用的那个输出流);
InputStream in = s.getInputStream();
// 4.通过输入流得到客户端发送的数据;
int len = -1;
byte[] bArray = new byte[1024];
while((len=in.read(bArray)) != -1){
// 5.展示数据;
System.out.println(new String(bArray,0,len));
}
// 6.关闭流,socket和ServerSocket对象;
//in.close();
//------以上代码完成了接收的功能-------------------
//------下面要给客户端返回一个数据----------------------------
OutputStream out = s.getOutputStream();
out.write("好的,我一定等你!".getBytes());
out.close();
s.close();
ss.close();
}
}
把客户端中的一个文件的数据读取出来,通过网络发送给服务器端,服务器端接收数据,并将其写到目标文件中;
与上面TCP协议编程i相比,区别在于:
1.客户端发送的数据 是从 文件中读取的;
2.服务器端把接收到的数据写到 一个目标文件中;
示例代码:
1.客户端程序
public class Client{
public static void main(String[] args)throws Excpention{
// 1.创建一个Socket对象,作为客户端;
Socket s = new Socket("192.168.186.50", 6000);
// 2.通过Socket对象得到输出流,用于把要发送的数据写到服务器端;
OutputStream out = s.getOutputStream();
// 3.创建一个输入流对象,用于从文件中读取数据
FileInputStream fis = new FileInputStream("E:\\2.jpg");
int n = -1;
byte[] b = new byte[1024];
while((n=fis.read(b)) != -1){
// 3.使用输出流写数据(发送数据);
out.write(b,0,n);
}
// 4.告诉服务器端发送已经完成;
s.shutdownOutput();
//----接收服务器端发送的数据--------------------
InputStream in = s.getInputStream();
int len = -1;
byte[] bArray = new byte[1024];
while((len=in.read(bArray)) != -1){
// 5.展示数据;
System.out.println(new String(bArray,0,len));
}
in.close();
// 6.关闭流,关闭Socket;
s.close();
}
}
2.服务器端程序
public class Server {
public static void main(String[] args) throws Exception {
// 1.创建一个ServerSocket对象,作为服务器端;
ServerSocket ss = new ServerSocket(6000);
// 2.调用ServerSocket对象的accept方法,接收数据,返回的是Socket对象,它对应了客户端对象
Socket s = ss.accept();
// 3.通过Socket对象得到一个输入流(客户端发送数据使用的那个输出流);
InputStream in = s.getInputStream();
// 创建一个输出流对象,用于把读到的数据写到目标文件中
FileOutputStream fos = new FileOutputStream("E:\\"+System.currentTimeMillis()+".jpg");
// 4.通过输入流得到客户端发送的数据;
int len = -1;
byte[] bArray = new byte[1024];
while((len=in.read(bArray)) != -1){
// 5.展示数据;
fos.write(bArray,0,len);
}
fos.close();
// 6.关闭流,socket和ServerSocket对象;
//in.close();
//------以上代码完成了接收的功能-------------------
//------下面要给客户端返回一个数据----------------------------
OutputStream out = s.getOutputStream();
out.write("文件上传成功!".getBytes());
out.close();
s.close();
ss.close();
}
}
1.只是修改了服务器端代码:
(1)把接收和处理客户端发送的数据代码放到一个while死循环中,让服务器端一直处于等待客户端上传的状态.
(2)把接收数据和写数据到木目标文件的代码使用一个子线程来处理,异步的处理多个客户端上传文件,避免阻塞;
代码如下:
public class Server {
public static void main(String[] args) throws Exception {
// 1.创建一个ServerSocket对象,作为服务器端;
ServerSocket ss = new ServerSocket(6000);
while(true){
// 2.调用ServerSocket对象的accept方法,接收数据,返回的是Socket对象,它对应了客户端对象
final Socket s = ss.accept();
new Thread(){
public void run() {
try {
// 3.通过Socket对象得到一个输入流(客户端发送数据使用的那个输出流);
InputStream in = s.getInputStream();
// 创建一个输出流对象,用于把读到的数据写到目标文件中
FileOutputStream fos = new FileOutputStream("E:\\"+System.currentTimeMillis()+".jpg");
// 4.通过输入流得到客户端发送的数据;
int len = -1;
byte[] bArray = new byte[1024];
while((len=in.read(bArray)) != -1){
// 5.展示数据;
fos.write(bArray,0,len);
}
fos.close();
// 6.关闭流,socket和ServerSocket对象;
//in.close();
//------以上代码完成了接收的功能-------------------
//------下面要给客户端返回一个数据----------------------------
OutputStream out = s.getOutputStream();
out.write("文件上传成功!".getBytes());
out.close();
s.close();
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}
//ss.close();
}
}