网络编程
一.网络通信协议
1.网络协议
不同的操作系统,不同的硬件设备上都能够联网,是因为互联网设计规定了一套标准,这套标准就被称为网络协议,网络协议规定了网络传输的格式,速率和方式;
2.TCP/IP协议
是一组协议:HTTP ,FTP,SMTP,DNS
TCP:传输控制协议
IP:互联网协议
TCP/IP协议的分层:
应用层:上位机应用程序,比如说qq,用来产生数据和显示数据
传输层:端口号 加入一些标志位,保证数据传输的准确性
网络层:ip地址 用来寻找对方电脑在哪里
链路层:网卡驱动 用来发送或接收数据
3. IP地址:
在一个网络中ip地址可以唯一标识一台电脑。
ipv4:xxx.xxx.xxx.xxx 点分十进制 32个二进制位来描述ip:21个亿
ipv6:128个二进制位来描述ip:无数个
4.端口号:
就是联网的每一个应用程序制定一个编号,编号可以唯一标识一个应用程序
1-65535
1-1024:系统使用
1024-6000:系统保留
>6000自己使用
一台电脑的应用程序想和另一台电脑的一个程序通信 必须知道ip地址和端口号
二.UDP 和TCP协议
1.udp协议:用户数据报协议
面向无连接的协议,两台电脑在通信之前不需要建立连接,发送端只管发送,不会关心接收端是否已经收到,或者接收端是否存在
优点:数据传输速度快,效率高
缺点:数据安全性不高,数据容易丢失;
应用场景:电话会议,视频直播,网络会议---->实时性
2.tcp协议:传输控制协议
两台电脑在通信之前必须建立连接(三次握手),每次发送完数据,都会有一个反馈信息。
优点:数据安全性高,可靠性强
缺点:传输数度慢,效率低
应用场景:密码管理,金融支付,理财系统
三.InetAddress类
1 /* 2 * InetAddress类用来描述一台电脑的信息:ip地址,计算机名和其他信息 3 * public static InetAddress getLocalHost();可以获取本地电脑主机的信息 4 * public static InetAddress getByName(String host);可以获取任意电脑主机的信息 5 */ 6 public static void main(String[] args)throws Exception { 7 //获取本地电脑主机的信息 8 InetAddress address=InetAddress.getLocalHost(); 9 //使用getHostAddress()方法获取本地的ip地址 10 String ip=address.getHostAddress(); 11 //使用getHostName()方法获取本地主机名 12 String hostName=address.getHostName(); 13 //-------------------------getByName()方法的使用--------------------------------- 14 //获取指定指定主机的电脑信息 15 InetAddress bdAddress=InetAddress.getByName("www.baidu.com");//这里参数可以是网址,ip地址,和主机名 16 //获取百度的ip地址 17 String baiDuIp=bdAddress.getHostAddress(); 18 System.out.println("百度的IP地址是:"+baiDuIp); 19 //获取百度的主机名 20 String baiDuHostName=bdAddress.getHostName(); 21 System.out.println("百度的主机名是:"+baiDuHostName); 22 }
四.UDP编程
1.使用udp实现发送端的编写:
1 public class SendDemo { 2 3 public static void main(String[] args) throws IOException { 4 //1:建立一个码头,该程序有一个对外连接的窗口 5 /* 6 * 套接字 7 */ 8 DatagramSocket ds = new DatagramSocket(); 9 //2:准备要发送的货物:数据 10 byte[] bytes = "hello udp!!!!".getBytes(); 11 12 //3:准备一个集装箱,将货物取装入集装箱 13 /* 14 * 参1:你要发送的数据 15 * 参2:你要发送的字节长度 16 * 参3: 表示接收端的ip地址 17 * 参4: 表示接收端的端口号 18 */ 19 //"192.168.65.103" --->InetAddress 20 InetAddress address = InetAddress.getByName("192.168.65.255"); 21 DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, 8888); 22 //4: 发送集装箱 23 ds.send(dp); 24 //5:关流 25 ds.close(); 26 } 27 28 }
2.使用udp协议实现接收端编写:
1 public class ReceiveDemo { 2 3 public static void main(String[] args) throws IOException { 4 //1:建立一个码头,并绑定端口 5 DatagramSocket ds = new DatagramSocket(8888); 6 //2:准备一个空的集装箱,用来接收数据 7 /* 8 * 参1:表示要接收的数据存放在哪个字节数组 9 * 参2:表示要接收的数据长度 10 */ 11 byte[] bytes = new byte[1024]; //"hello" ip 和端口 12 DatagramPacket dp = new DatagramPacket(bytes, bytes.length); 13 //3:接收数据 14 ds.receive(dp); //如果没有接收到数据,则该方法阻塞 15 //4:从集装箱中获取数据 16 byte[] data = dp.getData(); //"hello" 17 int length = dp.getLength(); 18 //获取发送端的ip 19 InetAddress address = dp.getAddress(); 20 String ip = address.getHostAddress(); 21 //5:打印接收到的数据 22 System.out.println(ip+":"+new String(data,0,length)); 23 } 24 25 }
五.TCP编程
交互流程图:
图片上传案例:
客户端的编写:
1 public class ClientDemo { 2 public static void main(String[] args) throws IOException { 3 //1:获取文件的输入流(读) 4 FileInputStream fis = new FileInputStream("a.jpg"); 5 6 // BufferedInputStream bufis = new BufferedInputStream(fis); 7 8 //2:获取套接字的输出流 9 InetAddress address = InetAddress.getLocalHost(); 10 Socket socket = new Socket(address, 9999); 11 OutputStream os = socket.getOutputStream(); 12 // BufferedOutputStream bufos = new BufferedOutputStream(os); 13 14 //3:将从文件输入流读取的数据写到套接字的输出流 15 byte[] bytes = new byte[1024]; 16 int len = 0; 17 while((len = fis.read(bytes)) != -1){ 18 os.write(bytes,0,len); 19 } 20 //关闭输出流 21 // socket.close(); //输入流和输出流都关闭 22 socket.shutdownOutput(); //值关闭输出流 23 //--接收反馈信息 24 //3.1获取套接字的输入流 25 InputStream is = socket.getInputStream(); 26 //3.2 读取数据 27 len = is.read(bytes); 28 System.out.println(new String(bytes,0,len)); 29 //4:关流 30 socket.close(); 31 fis.close(); 32 } 33 34 }
服务器端的编写:
1 public class ServerDemo { 2 public static void main(String[] args) throws IOException { 3 //1:获取套接字的输入流 4 ServerSocket sSocket = new ServerSocket(9999); 5 Socket cSocket = sSocket.accept(); 6 InputStream is = cSocket.getInputStream(); 7 8 //2:获取文件的输出流 9 FileOutputStream fos = new FileOutputStream("D:\\Server\\a.jpg"); 10 /* 11 * while循环要想结束必须read方法读取-1,在普通文件的读取中,读取到文件末尾就能-1 12 * 但是套接字没有文件末尾,所以不能返回-1 13 * 14 * 如何让服务器读取到-1? 15 * 只要让客户端把输出流进行关闭 16 */ 17 //3:将从套接字输入流读取的数据写入文件的输出流 18 byte[] bytes = new byte[1024]; 19 int len = 0; 20 while((len = is.read(bytes)) != -1){ 21 fos.write(bytes, 0, len); 22 } 23 //--在这里给客户端反馈 24 //3.1 获取套接字的输出流 25 OutputStream os = cSocket.getOutputStream(); 26 //3.2 发送反馈信息 27 os.write("上传成功啦!".getBytes()); 28 //4:关流 29 fos.close(); 30 cSocket.close(); 31 sSocket.close(); 32 } 33 }
多图片上传案例:
客户端:
1 public class ClientDemo { 2 3 public static void main(String[] args) throws IOException { 4 //1:获取文件的输入流(读) 5 FileInputStream fis = new FileInputStream("a.jpg"); 6 7 // BufferedInputStream bufis = new BufferedInputStream(fis); 8 9 //2:获取套接字的输出流 10 InetAddress address = InetAddress.getLocalHost(); 11 Socket socket = new Socket(address, 10086); 12 OutputStream os = socket.getOutputStream(); 13 // BufferedOutputStream bufos = new BufferedOutputStream(os); 14 15 //3:将从文件输入流读取的数据写到套接字的输出流 16 byte[] bytes = new byte[1024]; 17 int len = 0; 18 while((len = fis.read(bytes)) != -1){ 19 os.write(bytes,0,len); 20 } 21 //关闭输出流 22 // socket.close(); //输入流和输出流都关闭 23 socket.shutdownOutput(); //值关闭输出流 24 //--接收反馈信息 25 //3.1获取套接字的输入流 26 InputStream is = socket.getInputStream(); 27 //3.2 读取数据 28 len = is.read(bytes); 29 System.out.println(new String(bytes,0,len)); 30 //4:关流 31 socket.close(); 32 fis.close(); 33 } 34 35 }
服务器端:
1 public class ServerDemo { 2 public static void main(String[] args) throws IOException { 3 ServerSocket sSocket = new ServerSocket(10086); 4 //有多少个请求,accept就执行多少次 5 while(true){ 6 Socket cSocket = sSocket.accept(); 7 //每来一个请求,就创建一个线程,去处理请求 8 Thread t = new Thread(new MyRunnable(cSocket)); 9 t.start(); 10 } 11 } 12 }
多线程:
1 public class MyRunnable implements Runnable { 2 private Socket cSocket; 3 4 public MyRunnable(Socket cSocket) { 5 this.cSocket = cSocket; 6 } 7 8 public MyRunnable() { 9 } 10 //a.txt --->a(2).txt 11 @Override 12 public void run() { 13 try { 14 //1: 获取套接字的输入流 15 InputStream is = cSocket.getInputStream(); 16 long time = System.currentTimeMillis(); 17 18 //2:获取文件的输出流 19 FileOutputStream fos = new FileOutputStream("D:\\Server\\"+time+".jpg"); 20 21 //3:将从套接字输入流读取的数据写入文件的输出流 22 byte[] bytes = new byte[1024]; 23 int len = 0; 24 while((len = is.read(bytes)) != -1){ 25 fos.write(bytes, 0, len); 26 } 27 System.out.println("while之后"); 28 29 //--在这里给客户端反馈 30 //3.1 获取套接字的输出流 31 OutputStream os = cSocket.getOutputStream(); 32 //3.2 发送反馈信息 33 os.write("上传成功啦!".getBytes()); 34 35 //4:关流 36 fos.close(); 37 cSocket.close(); 38 } catch (Exception e) { 39 } 40 } 41 42 }