一、网络通信的三要素
1.1 网络通信的三要素:id、端口、协议
IP:设备在网络中的地址,是唯一的标识。
端口:应用程序在设备中唯一的标识
分为周知端口、注册端口、动态端口
注意事项:我们自己开发的程序一般选择使用注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错。
协议:连接和数据在网络中传输的规则。
TCP/IP网络模型:国际上大致分为应用层、传输层、网络层、数据链路层+物理,而TCP和UDP协议在传输层。
1.2 TCP协议和UDP协议的区别:
TCP协议:
特点:无连接、不可靠通信。
不事先建立连接,数据按照包发,一包数据包含:自己的IP、程序端口,目的地IP、程序端口和数据(限制在64KB内)等。
发送方不管对方是否在线,数据在中间丢失也不管,如果接收方收到数据也不返回确认,故是不可靠的 。
应用场景:视频直播
UDP协议:
特点:面向连接、可靠通信。速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据。
TCP的最终目的:要保证在不可靠的信道上实现可靠的传输。
TCP主要有三个步骤实现可靠传输:三次握手建立连接,传输数据进行确认,四次挥手断开连接。
应用场景:网页、文件下载、支付
二、UDP、TCP快速入门
2.1 UDP的入门案例
具体步骤:1.创建发送端的Socket对象(要指定接收端的端口号)、创建一个数据包用来存储数据2.创建接收端的Socket对象、定义一个字节数组接收。
Demo
public class Receiver {
public static void main(String[] args) throws Exception {
//接收端要写端口号!
DatagramSocket socket = new DatagramSocket(9998);
//空的数组存放
byte[] bytes = new byte[1024*8];
DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
packet.getLength();
socket.receive(packet);
String s = new String(bytes,0,packet.getLength());
System.out.println(s);
}
}
public class Sender {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket();
Scanner sc = new Scanner(System.in);
String str = sc.next();
System.out.println("请输入内容(end结束):");
byte[] bytes = str.getBytes();
DatagramPacket packet = new DatagramPacket(bytes,0, bytes.length, InetAddress.getByName("127.0.0.1"),9998);
socket.send(packet);
}
}
2.2 TCP的入门案例
客户端实现步骤:创建客户端的Socket对象,请求与服务端的连接。 使用socket对象调用getOutputStream()方法得到字节输出流。 使用字节输出流完成数据的发送。 释放资源:关闭socket管道。
接收端实现步骤:创建ServerSocket对象,注册服务端端口。 调用ServerSocket对象的accept()方法,等待客户端的连接,并得到Socket管道对象。 通过Socket对象调用getInputStream()方法得到字节输入流、完成数据的接收。 释放资源:关闭socket管道
Demo
public class Service {
public static void main(String[] args) throws Exception {
//创建ServerSocket对象,并且调用accept方法完成与客服端的连接
while (true) {
ServerSocket socket = new ServerSocket(9998);
Socket socket1 = socket.accept();
//调用InputStream()方法,输入流接收数据
InputStream is = socket1.getInputStream();
byte[] bytes = new byte[1024*8];
int length = is.read(bytes);
String s = new String(bytes,0,length);
System.out.println("接受到客服端传输过来的:"+s);
//关闭
is.close();
socket.close();
}
}
}
public class Client {
public static void main(String[] args) throws Exception {
//创建Socket对象,并且与服务器连接
Socket socket = new Socket("127.0.0.1",9998);
String s = "在吗,在干嘛?";
OutputStream os = null;
while (true) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入内容:");
String str = sc.next();
//使用输出流读完成数据的发送
os = socket.getOutputStream();
os.write(str.getBytes());
os.close();
socket.close();
}
//关闭
}
三、UDP、TCP多发多收
UDP的接收端怎么实现可以接收很多发送端的消息?
发送端循环发送数据,接收端循环接收数据
Demo
public class Client {
public static void main(String[] args)throws Exception {
//创建发送端
DatagramSocket socket = new DatagramSocket();
Scanner sc = new Scanner(System.in);
while (true){
System.out.println("请输入内容:");
String ins = sc.next();
//判断结束
if (ins.equals("end")){
socket.close();
break;
}
//定义一个byte数组发送数据
byte[] bytes = ins.getBytes();
int l = bytes.length;
//创建数据包
DatagramPacket packet = new DatagramPacket(bytes,0,l, InetAddress.getLocalHost(),998);
socket.send(packet);
}
}
}
public class Service {
public static void main(String[] args)throws Exception {
//创建接收端
DatagramSocket socket = new DatagramSocket(998);
byte[] bytes = new byte[1024*8];
//创建数据包
DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
while (true){
//接收数据
socket.receive(packet);
//获取数据的长度
int l = packet.getLength();
//数据转化为字符串打印
String str = new String(bytes,0,l);
System.out.println("传输过来的数据是:"+str);
}
}
}
TCP的多传多发:
客户端使用死循环,让用户不断输入消息。 服务端也使用死循环,控制服务端收完消息,继续等待接收下一个消息。
Demo
public class Client {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1",9998);
//创建键盘输入
OutputStream os = null;
InputStream is = null;
while (true) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入内容:");
String str = sc.next();
//获取一个输出流,获取上面内容
if (str.equals("end")){
socket.shutdownOutput();//关闭输出流
break;
}
os = socket.getOutputStream();
os.write(str.getBytes());
//获取输入流
is = socket.getInputStream();
byte[] bytes = new byte[1024*8];
int length = is.read(bytes);
String s = new String(bytes,0,length);
System.out.println("传输过来的数据是:"+s);
}
//关闭
/*os.close();
is.close();*/
}
}
public class Service {
public static void main(String[] args) throws Exception {
InputStream is = null;
OutputStream os = null;
while (true) {
//创建服务器对象
ServerSocket socket = new ServerSocket(9998);
//接收对方的socket
Socket accept = socket.accept();
//获得输入流,读取对方传输过来的数据
is = accept.getInputStream();
byte[] bytes = new byte[1024*8];
int length = is.read(bytes);
if (length == -1){
break;
}
String s = new String(bytes,0,length);
System.out.println("接收到客户端的数据:"+s);
//获得输出流,把数据传输过去
os = accept.getOutputStream();
os.write("我接收到你的数据啦".getBytes());
}
//关闭
//is.close();
//os.close();
}
}