可以让设备中的程序与网络上的其他设备中的成勋数据交互(实现网络通讯)
java.net.*包下提供了网络编程的解决方案
- CS架构:(Client客户端 / Server服务端)
- BS架构: (Browser浏览器 / Server服务端)
ip地址:(cmd -> ipconfig:IPv4(32字节))
设备在网络中的唯一标识(上网设备上的身份号码)
IP地址的两种形式:IPv4(32字节)、IPv6(128位):号称可以为地球上每一粒沙子编号
IP域名:记录了服务器的ip
公网IP:是可以链接互联网的IP地址
内网ip也局域网ip,只能组织机构内部使用
192.168.开头的都是常见的局域网地址
192.168.00--192.168.255.255专门为组织机构内部使用
127.0.0.1 、 localhost本机IP,只会寻找当前所在主机
import java.io.IOException; import java.net.InetAddress; public class InetAddressText { public static void main(String[] args) throws IOException { //获取本机的IP地址对象 InetAddress ip1 = InetAddress.getLocalHost(); System.out.println(ip1.getHostName()); System.out.println(ip1.getHostAddress()); ///获取指定的ip或则域名的IP地址对象 InetAddress ip2 = InetAddress.getByName("www.baidu.com"); System.out.println(ip2.getHostName()); System.out.println(ip2.getHostAddress()); //相当于ping System.out.println(ip2.isReachable(6000)); } }端口:(可以标志0-65535个应用程序)(自己开发的程序用注册端口号)
应用程序在设备中唯一的标识
周知端口:0-1023,被预先定义的知名应用占用(http80、ftp21)
注册端口:1024-49151,分配给用户进程或某些应用程序
动态端口:49152-65535,之所以被称为动态端口,是因为她一般不固定分配某种进程,而是动态分配
协议:
链接和数据在网络中传输的规则
开放式网络互连标准:()
osi网络参考模型:全球网络互联网标准
TCP/IP网络模型:事实上的国际标准
传输层2个通讯协议
UDP(用户数据协议),TCP传输控制协议
UDP协议:
- 特点:无连接,不可靠通讯
- 不事先建立链接,数据按照包发,一包数据包含:自己的ip、程序端口、目的IP、程序端口和数据(限制在64KB内)等等。
- 发送不管对方是否在线,数据在中间丢失也不管,如果接受方收到数据也不返回确认
- 通讯效率高,视频,通话应用
TCP协议:
- 特点:面向链接,可靠通讯
- tcp的最终目的:要保证在不可靠的信道上实现可靠传输
- YCP主要有三个步骤实现可靠传输:三次握手建立链接,传输数据进行确认。四次挥手断开连接
- 三次握手:发出链接请求、返回一个响应、发出确认信息,确认链接、
- 四次挥手:发出断开请求、返回一个响应:稍等、返回一个响应,确认断开、发出正式确认断开链接
java提供了Java.net.DatagramSocket类来实现UDP通讯
DatagramSocket类:用于创建客户端、服务端:
客户端:
package com.Game_All.UDP; import java.io.IOException; import java.net.*; public class Client { public static void main(String[] args) throws IOException { //1、创建客户端对象 DatagramSocket socket = new DatagramSocket(); //2、创建数据包对象 /*public DatagramPacket(byte buf[], int length, InetAddress address, int port) { this(buf, 0, length, address, port);*/ byte[] bytes = "我是快乐的客户端,我爱你黄洁".getBytes(); /* 参数一:封装要发出去的数据。 参数二:发送出去的数据大小(字节个数) 参数三:服务端的TP地址(找到服务端主机) 参数四:服务端程序的端口 */ DatagramPacket packet = new DatagramPacket(bytes,bytes.length,InetAddress.getLocalHost(),6666); //3、发送 socket.send(packet); System.out.println("客户端发送完毕"); socket.close();//释放资源 } }服务端:
package com.Game_All.UDP; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class Server { public static void main(String[] args) throws IOException { //1、创建一个服务端(注册端口) DatagramSocket socket = new DatagramSocket(6666); //2、创建一个数据包对象,用于接收数据的 byte[] buffer = new byte[1024*64];//64kb DatagramPacket packet = new DatagramPacket(buffer,buffer.length); //3、接收 socket.receive(packet); //4、从字节数组中,吧即受到的数据直接打印出来 //接收到多少就到处多少 int len = packet.getLength(); String rs = new String(buffer,0,len); System.out.println(rs); System.out.println(packet.getAddress().getHostAddress()); System.out.println(packet.getPort()); socket.close(); } }先运行服务端!!!!
多发多收
package com.Game_All.UDP; import java.io.IOException; import java.net.*; import java.util.Scanner; public class Client { public static void main(String[] args) throws IOException { //1、创建客户端对象 DatagramSocket socket = new DatagramSocket(); //2、创建数据包对象 /*public DatagramPacket(byte buf[], int length, InetAddress address, int port) { this(buf, 0, length, address, port);*/ /* 参数一:封装要发出去的数据。 参数二:发送出去的数据大小(字节个数) 参数三:服务端的TP地址(找到服务端主机) 参数四:服务端程序的端口 */ Scanner scan = new Scanner(System.in); while (true){ System.out.println("请说:"); String msg = scan.nextLine(); if ("exit".equals(msg)){ System.out.println("欢迎下次光临!退出成功"); socket.close(); break; } byte[] bytes = msg.getBytes(); DatagramPacket packet = new DatagramPacket(bytes,bytes.length,InetAddress.getLocalHost(),6666); //3、发送 socket.send(packet); } } } package com.Game_All.UDP; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class Server { public static void main(String[] args) throws IOException { //1、创建一个服务端(注册端口) DatagramSocket socket = new DatagramSocket(6666); //2、创建一个数据包对象,用于接收数据的 byte[] buffer = new byte[1024*64];//64kb DatagramPacket packet = new DatagramPacket(buffer,buffer.length); while (true) { //3、接收 socket.receive(packet); //4、从字节数组中,吧即受到的数据直接打印出来 //接收到多少就到处多少 int len = packet.getLength(); String rs = new String(buffer,0,len); System.out.println(rs); System.out.println(packet.getAddress().getHostAddress()); System.out.println(packet.getPort()); System.out.println("======================="); } } }
package com.Game_All.TCP; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; public class Client { public static void main(String[] args) throws IOException { //1、创建Socket对象,并同时请求与服务端程序的链接 Socket socket = new Socket("127.0.0.1",8888); //2、从socket通信管道中得到一个字节输出流,用来发数据给服务端程序 OutputStream os = socket.getOutputStream(); //3、把低级的字节输出流包装成数据输出流 DataOutputStream dos = new DataOutputStream(os); //4、开始写数据出去了 dos.writeUTF("在一起,好嘛"); dos.close(); socket.close(); } }
package com.Game_All.TCP; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; public class Client { public static void main(String[] args) throws IOException { //1、创建Socket对象,并同时请求与服务端程序的链接 Socket socket = new Socket("127.0.0.1",8888); //2、从socket通信管道中得到一个字节输出流,用来发数据给服务端程序 OutputStream os = socket.getOutputStream(); //3、把低级的字节输出流包装成数据输出流 DataOutputStream dos = new DataOutputStream(os); //4、开始写数据出去了 dos.writeUTF("在一起,好嘛"); dos.close(); socket.close(); } }
package com.Game_All.TCP; import java.io.DataInputStream; import java.io.DataOutputStream; 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) throws IOException { //1、创建ServerSocket的对象,同时为服务端的注册端口 ServerSocket serverSocket = new ServerSocket(8888); //2、使用ServerSocket对象,调用一个accpte方法等待对象的客户链接请求 Socket socket = serverSocket.accept(); //3、从socke通信管道中的一个字节输入流 InputStream is = socket.getInputStream(); //4、把原始的字节输入流包装成数据输入流 DataInputStream dis = new DataInputStream(is); //5、使用数据输入流读取客户端发送过来的消息 String re = dis.readUTF(); System.out.println(re); //获取客户端IP地址 System.out.println(socket.getRemoteSocketAddress()); dis.close(); socket.close(); } }多发多收
package com.Game_All.TCP; import java.io.DataInputStream; import java.io.DataOutputStream; 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) throws IOException { //1、创建ServerSocket的对象,同时为服务端的注册端口 ServerSocket serverSocket = new ServerSocket(8888); //2、使用ServerSocket对象,调用一个accpte方法等待对象的客户链接请求 Socket socket = serverSocket.accept(); //3、从socke通信管道中的一个字节输入流 InputStream is = socket.getInputStream(); //4、把原始的字节输入流包装成数据输入流 DataInputStream dis = new DataInputStream(is); while (true){ try { //5、使用数据输入流读取客户端发送过来的消息 String re = dis.readUTF(); System.out.println(re); //获取客户端IP地址 System.out.println(socket.getRemoteSocketAddress()); System.out.println("---------------------"); } catch (IOException e) { System.out.println(socket.getRemoteSocketAddress()+"离线了"); dis.close(); socket.close(); break; } } } } package com.Game_All.TCP; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; public class Client { public static void main(String[] args) throws IOException { //1、创建Socket对象,并同时请求与服务端程序的链接 Socket socket = new Socket("127.0.0.1",8888); //2、从socket通信管道中得到一个字节输出流,用来发数据给服务端程序 OutputStream os = socket.getOutputStream(); //3、把低级的字节输出流包装成数据输出流 DataOutputStream dos = new DataOutputStream(os); Scanner scanner = new Scanner(System.in); //4、开始写数据出去了 while (true){ System.out.println("请说:"); String msg = scanner.nextLine(); if ("exit".equals(msg)){ dos.close(); socket.close(); break; } dos.writeUTF(msg); dos.flush(); } } }不支持多个客户一个服务器
服务端
package com.Game_All.TCP; import java.io.DataInputStream; import java.io.DataOutputStream; 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) throws IOException { //1、创建ServerSocket的对象,同时为服务端的注册端口 ServerSocket serverSocket = new ServerSocket(8888); while (true) { try { //2、使用ServerSocket对象,调用一个accpte方法等待对象的客户链接请求 Socket socket = serverSocket.accept(); System.out.println("有人上线了"+socket.getRemoteSocketAddress()); //3、把这个客户端对应的socket通信管道,交给一个独立的线程负责处理 new ServiceReaderThread(socket).start(); } catch (IOException e) { throw new RuntimeException(e); } } } } package com.Game_All.TCP; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.net.Socket; public class ServiceReaderThread extends Thread{ private Socket socket; public ServiceReaderThread(Socket socket) { this.socket = socket; } @Override public void run() { InputStream is = null; try { is = socket.getInputStream(); DataInputStream dis = new DataInputStream(is); while (true){ try { String msg = dis.readUTF(); System.out.println(msg); } catch (IOException e) { System.out.println("有人下线了"+socket.getRemoteSocketAddress()); dis.close(); socket.close(); break; } } } catch (IOException e) { throw new RuntimeException(e); } } }客户端两个:
package com.Game_All.TCP; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; public class Client { public static void main(String[] args) throws IOException { //1、创建Socket对象,并同时请求与服务端程序的链接 Socket socket = new Socket("127.0.0.1",8888); //2、从socket通信管道中得到一个字节输出流,用来发数据给服务端程序 OutputStream os = socket.getOutputStream(); //3、把低级的字节输出流包装成数据输出流 DataOutputStream dos = new DataOutputStream(os); Scanner scanner = new Scanner(System.in); //4、开始写数据出去了 while (true){ System.out.println("请说:"); String msg = scanner.nextLine(); if ("exit".equals(msg)){ dos.close(); socket.close(); break; } dos.writeUTF(msg); dos.flush(); } } } package com.Game_All.TCP; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; public class Client1 { public static void main(String[] args) throws IOException { //1、创建Socket对象,并同时请求与服务端程序的链接 Socket socket = new Socket("127.0.0.1",8888); //2、从socket通信管道中得到一个字节输出流,用来发数据给服务端程序 OutputStream os = socket.getOutputStream(); //3、把低级的字节输出流包装成数据输出流 DataOutputStream dos = new DataOutputStream(os); Scanner scanner = new Scanner(System.in); //4、开始写数据出去了 while (true){ System.out.println("请说:"); String msg = scanner.nextLine(); if ("exit".equals(msg)){ dos.close(); socket.close(); break; } dos.writeUTF(msg); dos.flush(); } } }
客户端
package com.Game_All.TCP; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; public class Client { public static void main(String[] args) throws IOException { //1、创建Socket对象,并同时请求与服务端程序的链接 Socket socket = new Socket("127.0.0.1",8888); //创建一个独立的线程,随机负责从socket中获取服务端发送过拉力的信息 new ClientReaderThread(socket).start(); //2、从socket通信管道中得到一个字节输出流,用来发数据给服务端程序 OutputStream os = socket.getOutputStream(); //3、把低级的字节输出流包装成数据输出流 DataOutputStream dos = new DataOutputStream(os); Scanner scanner = new Scanner(System.in); //4、开始写数据出去了 while (true){ System.out.println("请说:"); String msg = scanner.nextLine(); if ("exit".equals(msg)){ dos.close(); socket.close(); break; } dos.writeUTF(msg); dos.flush(); } } }
package com.Game_All.TCP; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.net.Socket; public class ClientReaderThread extends Thread{ private Socket socket; public ClientReaderThread(Socket socket) { this.socket = socket; } @Override public void run() { try { InputStream is = socket.getInputStream(); DataInputStream dis = new DataInputStream(is); while (true){ try { String msg = dis.readUTF(); System.out.println(msg); } catch (IOException e) { System.out.println("有人下线了"+socket.getRemoteSocketAddress()); Server.onLineSocket.remove(socket); dis.close(); socket.close(); break; } } } catch (IOException e) { e.printStackTrace(); } } }服务端
package com.Game_All.TCP; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; public class Server { public static ListonLineSocket = new ArrayList<>(); public static void main(String[] args) throws IOException { //1、创建ServerSocket的对象,同时为服务端的注册端口 ServerSocket serverSocket = new ServerSocket(8888); while (true) { try { //2、使用ServerSocket对象,调用一个accpte方法等待对象的客户链接请求 Socket socket = serverSocket.accept(); System.out.println("有人上线了"+socket.getRemoteSocketAddress()); onLineSocket.add(socket); //3、把这个客户端对应的socket通信管道,交给一个独立的线程负责处理 new ServiceReaderThread(socket).start(); } catch (IOException e) { throw new RuntimeException(e); } } } }
package com.Game_All.TCP; import java.io.*; import java.net.Socket; import java.util.ArrayList; import java.util.List; public class ServiceReaderThread extends Thread{ private Socket socket; public ServiceReaderThread(Socket socket) { this.socket = socket; } @Override public void run() { InputStream is = null; try { is = socket.getInputStream(); DataInputStream dis = new DataInputStream(is); while (true){ try { String msg = dis.readUTF(); System.out.println(msg); //把这个信息分发给所有客户端接收 sendMsgToAll(msg); } catch (IOException e) { System.out.println("有人下线了"+socket.getRemoteSocketAddress()); Server.onLineSocket.remove(socket); dis.close(); socket.close(); break; } } } catch (IOException e) { throw new RuntimeException(e); } } private void sendMsgToAll(String msg) throws IOException { //发送给全部在线的socket管道接收 for (Socket onlineSocket : Server.onLineSocket) { OutputStream os = onlineSocket.getOutputStream(); DataOutputStream dos = new DataOutputStream(os); dos.writeUTF(msg); dos.flush(); } } }
package com.Game_All.TCP; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class Server { public static void main(String[] args) throws IOException { //1、创建ServerSocket的对象,同时为服务端的注册端口 ServerSocket serverSocket = new ServerSocket(8888); //创建一个县城其,负责处理铜鼓县你管道任务 ThreadPoolExecutor pool = new ThreadPoolExecutor(16*2,16*2,0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(8), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy()); while (true) { //2、使用ServerSocket对象,调用一个accpte方法等待对象的客户链接请求 Socket socket = serverSocket.accept(); //3、把这个客户端对应的socket通信管道,交给一个独立的线程负责处理 pool.execute(new ServiceReaderRunnable(socket)); } } }
package com.Game_All.TCP; import java.io.*; import java.net.Socket; public class ServiceReaderRunnable implements Runnable { private Socket socket; public ServiceReaderRunnable(Socket socket) { this.socket = socket; } @Override public void run() { try { OutputStream os = socket.getOutputStream(); PrintWriter out = new PrintWriter(os, true); out.println("HTTP/1.1 200 OK"); out.println("Content-Type: text/html; charset=UTF-8"); out.println(); out.println("Hello, World!"); out.close(); } catch (IOException e) { e.printStackTrace(); } finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }