目录
网络编程
两种软件架构
网络通信的三要素
IP
IPv4的地址分类
特殊IP
端口号
协议
用UDP协议发送数据
用UDP接收数据
TCP接收和发送数据
TCP通信--支持与多个客户端同时通信
网络编程
可以让设备中的程序与网络上其他设备的程序进行数据交互(实现网络通信)
两种软件架构
CS:在用户本地需要下载并安装客户端程序,在远程有一个服务器端程序
BS:只需要一个浏览器,用户通过不同的网址,客户访问不同的服务器
网络通信的三要素
IP
设备在网络中的地址,是唯一的标识
有IPv4和IPv6
最多有2^32次方的ip,目前用完了
IPv4中不够用,就有了IPv6
为了解决ipv4不够用而出现的,最多有2^128次方的ip
IPv4的地址分类
公网地址(万维网使用)和私有地址(局域网使用)
192.168.开头的就是私有地址,范围即为192.168.0.0--192.168.255.255,专门为组织机构内部使用,以此节约IP
特殊IP
127.0.0.1,也可以是localhost:是回送地址也称本地回环地址,也成为本机IP,永远只会寻找当前所在的本机
常用的CMD命令
ipconfig:查看本机IP地址
ping:检查网络是否连通
public class ip {public static void main(String[] args) throws UnknownHostException {// 1.获取InetAddress的对象// IP的对象 一台电脑对象InetAddress address = InetAddress.getByName("192.168.135.1");System.out.println(address);String name = address.getHostName();System.out.println(name);String ip = address.getHostAddress();System.out.println(ip);}
}
端口号
应用程序在设备中唯一的标识
端口号: 由两个字节表示的整数,取值范围:0-665535,其中0-1023之间的端口用于一些知名的网络服务或应用,我们自己使用1024以上的端口就可以了
协议
数据在网路中传输的规则
UDP协议: 用户数据报协议
UDP是面向无连接通信协议
速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据
TCP协议:传输控制协议
TCP协议是面向连接的通信协议
速度慢,没有大小限制,数据安全
下面是用UDP来发收数据
用UDP协议发送数据
public class ip {public static void main(String[] args) throws IOException {// 发送数据// 1.创建DatagramSocket对象// 细节://绑定端口,以后我们就是通过这个端口往外发送//有参:指定端口号进行绑定DatagramSocket ds = new DatagramSocket();// 打包数据String str = "hello world";byte[] bytes = str.getBytes(); // 将str转换成字节数组来用来打包数据InetAddress address = InetAddress.getByName("127.0.0.1"); // 表示那台ip电脑来接受int port=10086; //被发数据电脑接收的端口DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);// 3. 发送数据ds.send(dp);// 4.释放资源ds.close();}
}
用UDP接收数据
public class receive {public static void main(String[] args) throws IOException {// 接收数据// 1.创建DatagramSocket对象//我们可以做一个比喻: 这就是一个快递公司// 细节:// 接收和传输不一样:接收一定要绑定接口// 而且绑定的端口,一定要跟发送的端口保持一致DatagramSocket ds = new DatagramSocket(10086);// 2. 接收数据包byte[] bytes = new byte[1024];DatagramPacket dp = new DatagramPacket(bytes,bytes.length);ds.receive(dp);// 3.解析数据包byte[] data = dp.getData();int len = dp.getLength();InetAddress address = dp.getAddress();int port = dp.getPort();System.out.println("接收到数据" + new String(data,len));System.out.println("该数据是从"+address+"接口是"+port);// .释放资源ds.close();}
}
TCP接收和发送数据
通信双方事先会采用"三次握手"方式建立可靠连接,实现端到端的通信;底层能保证数据成功传到服务端
一发一收
创建客户端
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;public class Tcp {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();}
}
创建服务器
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;public class Res {public static void main(String[] args) throws IOException {System.out.println("------服务端启动成功------");// 1.创建ServerSocket的对象,同时为服务端注册端口ServerSocket serverSocket = new ServerSocket(8888);// 2.使用serverSocket对象,调用一个accept方法,等待客户端的连接请求Socket socket = serverSocket.accept();// 3. 从socket通信管道中得到一个字节输入流InputStream is = socket.getInputStream();//4.把原始的字节输入流包装成数据输入流DataInputStream dis = new DataInputStream(is);//5.使用数据输入流读取客户端发送的消息String rs = dis.readUTF();System.out.println(rs);// 其实我们也可以获取客户端的IP地址System.out.println(socket.getRemoteSocketAddress());dis.close();socket.close();}
}
多发多收
发送数据
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;public class Tcp {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 sc = new Scanner(System.in);while (true) {System.out.println("请说: ");String msg = sc.nextLine();// 一旦用户输入exit,就退出客户端程序if("exit".equals(msg)){System.out.println("欢迎你下次光临!退出成功");dos.close();socket.close();break;}//4.开始写数据出去了dos.writeUTF(msg);dos.flush();}}
}
接收数据
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;public class Res {public static void main(String[] args) throws IOException {System.out.println("------服务端启动成功------");// 1.创建ServerSocket的对象,同时为服务端注册端口ServerSocket serverSocket = new ServerSocket(8888);// 2.使用serverSocket对象,调用一个accept方法,等待客户端的连接请求Socket socket = serverSocket.accept();// 3. 从socket通信管道中得到一个字节输入流InputStream is = socket.getInputStream();//4.把原始的字节输入流包装成数据输入流DataInputStream dis = new DataInputStream(is);while (true) {try {//5.使用数据输入流读取客户端发送的消息String rs = dis.readUTF();System.out.println(rs);} catch (IOException e) {System.out.println(socket.getRemoteSocketAddress()+"离线了");socket.close();dis.close();break;}}}
}
TCP通信--支持与多个客户端同时通信
我们应该整一个多线程的写法,每个客户端写成一个线程
创建客户端
public class tcp {public static void main(String[] args) throws IOException {Socket socket = new Socket("127.0.0.1",9999);OutputStream os = socket.getOutputStream();DataOutputStream dos = new DataOutputStream(os);// 1. 多发多收Scanner sc = new Scanner(System.in);while (true) {String msg = sc.nextLine();if("886".equals(msg)){System.out.println("下线");break;}dos.writeUTF(msg);}}
}
创建服务端
public class res {public static void main(String[] args) throws IOException {ServerSocket serverSocket =new ServerSocket(9999);while (true) {Socket socket = serverSocket.accept();System.out.println("有人上线了"+socket.getRemoteSocketAddress());new SeverSocketThread(socket).start();}}
}
我们看看线程的写法
package TCP_test;import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;public class SeverSocketThread extends Thread{private Socket socket;public SeverSocketThread(Socket socket) {this.socket = socket;}@Overridepublic void run(){try {InputStream is = socket.getInputStream();DataInputStream dis = new DataInputStream(is);while (true) {try {String msg = dis.readUTF();System.out.println(msg);} catch (Exception e) {System.out.println("有人下线了"+socket.getRemoteSocketAddress());dis.close();is.close();socket.close();break;}}} catch (IOException e) {System.out.println(socket.getRemoteSocketAddress() + "下线");}}
}