Internet协议集支持一个无连接的传输协议,该协议称为用户数据报协议(User DatagramProtoco).UDP为应用程序提供了一种无需建立连接就可以发送封装的IP数据报的方法
Internet 的传输层有两个主要协议,互为补充。无连接的是 UDP,它除了给应用程序发送数据包功能并允许它们在所需的层次上架构自己的协议之外,几乎没有做什么特别的事情。面向连接的是 TCP,该协议几乎做了所有的事情。
UDP的特点
- 无连接:知道对方的IP和端口号就直接进行传输,不需要建立连接
- 不可靠:没有确认机制,没有重传机制;如果因为网络故障而无法到达对方,UDP协议层也不会给应用层返回任何错误信息
- 面向数据报文:不能够灵活控制读写数据的次数和数量
创建一个UDP服务器
package package1224;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Server {
public static void main(String[] args) throws IOException {
//创建一个服务器socke,同时绑定了一个8888端口,默认绑定的ip是所有ip
DatagramSocket socket = new DatagramSocket(8888);//8888是端口
while (true){
byte[] buffer = new byte[4096];//准备了一个接受缓冲区
//创建了一个接受报文
DatagramPacket receivePacket = new DatagramPacket(buffer,0,buffer.length);
//当receive 返回时,OS就会把
socket.receive(receivePacket);
//获取实际收到数据的长度
int len = receivePacket.getLength();
//字节转换为字符
String message = new String(buffer,0,len,"UTF-8");
//准备回给对方的消息,回声
String echoMessage = message;
System.out.println("收到了消息:" + message);
//把字符转字节
byte[] sendBuffer = echoMessage.getBytes("UTF-8");
//创建发送报文,带有发送缓冲区,对方ip,对方端口
DatagramPacket sendPacket = new DatagramPacket(
sendBuffer,
0,
sendBuffer.length,
receivePacket.getAddress(),
receivePacket.getPort()
);
//发送成功,只是代表数据发送到网络上了,不代表对方收到了
socket.send(sendPacket);
}
}
}
创建一个UDP客户端
package package1224;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Client {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket();
String message = "宫保鸡丁";
//创建一个发送缓冲区
byte[] sendBuffer = message.getBytes("UTF-8");
InetAddress address = InetAddress.getLoopbackAddress();
int port = 8888;//饭店端口
//创建一个发送报文
DatagramPacket sendPacket = new DatagramPacket(
sendBuffer,
0,
sendBuffer.length,
address,
port
);
socket.send(sendPacket);
//创建一个接受缓冲区
byte[] receiveBuffer = new byte[4096];
//创建一个接受报文
DatagramPacket receivePackt = new DatagramPacket(
receiveBuffer,
0,
receiveBuffer.length
);
socket.receive(receivePackt);
String echoMessage = new String(receiveBuffer,0,receiveBuffer.length,"UTF-8");
System.out.println(echoMessage);
socket.close();
}
}
我们可以对这个服务器做一些我们想要的东西
发送英文接受一个动物符号
//这是服务器
public class 图形转换Server {
private static Map<String,String> dictionary = new HashMap<>();
static {
try {
InputStream is = new FileInputStream("事先准备好的字典.txt");
Scanner scanner = new Scanner(is,"UTF-8");
while (scanner.hasNext()){
String line = scanner.nextLine();
String[] kv = line.split(":");
dictionary.put(kv[0],kv[1]);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static String translation(String eng){
return dictionary.getOrDefault(eng,"看不懂");
}
public static void main(String[] args) throws IOException {
//创建一个服务器socke,同时绑定了一个8888端口,默认绑定的ip是所有ip
DatagramSocket socket = new DatagramSocket(8888);//8888是端口
while (true){
byte[] buffer = new byte[4096];//准备了一个接受缓冲区
//创建了一个接受报文
DatagramPacket receivePacket = new DatagramPacket(buffer,0,buffer.length);
//当receive 返回时,OS就会把
socket.receive(receivePacket);
//获取实际收到数据的长度
int len = receivePacket.getLength();
//字节转换为字符
String message = new String(buffer,0,len,"UTF-8");
//准备回给对方的消息,回声
String echoMessage = translation(message);
//把字符转字节
byte[] sendBuffer = echoMessage.getBytes("UTF-8");
//创建发送报文,带有发送缓冲区,对方ip,对方端口
DatagramPacket sendPacket = new DatagramPacket(
sendBuffer,
0,
sendBuffer.length,
receivePacket.getAddress(),
receivePacket.getPort()
);
//发送成功,只是代表数据发送到网络上了,不代表对方收到了
socket.send(sendPacket);
}
}
}
运算
package package1224;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPServer {
private static String parse(String message){
String[] item = message.split(" ");
int a = Integer.valueOf(item[0]);
String operator = item[1];
int b = Integer.valueOf(item[2]);
int r;
switch (operator){
case "+" : r = a + b;break;
case "-" : r = a - b;break;
case "*" : r = a * b;break;
case "/" : r = a / b;break;
default:
r = -1;
}
return r + "";
}
public static void main(String[] args) throws IOException {
//创建一个服务器socke,同时绑定了一个8888端口,默认绑定的ip是所有ip
DatagramSocket socket = new DatagramSocket(8888);//8888是端口
while (true){
byte[] buffer = new byte[4096];//准备了一个接受缓冲区
//创建了一个接受报文
DatagramPacket receivePacket = new DatagramPacket(buffer,0,buffer.length);
//当receive 返回时,OS就会把
socket.receive(receivePacket);
//获取实际收到数据的长度
int len = receivePacket.getLength();
//字节转换为字符
String message = new String(buffer,0,len,"UTF-8");
System.out.println("收到一条消息 " + message);
//准备回给对方的消息,回声
String echoMessage = parse(message);
//把字符转字节
byte[] sendBuffer = echoMessage.getBytes("UTF-8");
//创建发送报文,带有发送缓冲区,对方ip,对方端口
DatagramPacket sendPacket = new DatagramPacket(
sendBuffer,
0,
sendBuffer.length,
receivePacket.getAddress(),
receivePacket.getPort()
);
//发送成功,只是代表数据发送到网络上了,不代表对方收到了
socket.send(sendPacket);
}
}
}
注意这里的Client就要改一下了,String message = scanner.nextLine();//发送字符
1UDP面向报文 无连接
只要读即可(无连接),读到的数据包一定是发送的数据(面向报文的特点)
.
2.TCP 面向连接,面向流
先accept然后read(面向连接),读到的数据可能不是你发送时的样子(面向流)