1.1 UDP协议特点:
- UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另
外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向
发送端反馈是否收到数据。
由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用
UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建
议使用UDP协议。UDP通信过程如下图所示:
- UDP ==> User DatagramPacket Protocol ==> 用户数据报包协议
- UDP协议的特点:(面试)
- 只管发送,不确认对方是否收到。
- 基于数据包(报)传输数据:将要发送的数据,接收端IP地址,端口号等信息打包到一个数据包中发送。
- 传输数据大小限制在64K以内。
- 速度快,但不可靠。(会出现数据丢失的情况)
- UDP协议的使用场景:
- 即时通讯(qq,微信,陌陌)
- 在线视频
- 网络语音电话
- UDP协议通讯两个相关的类:
- DatagramPacket
- 数据包对象
- 作用:用来封装要发送或接收的数据
- 比喻:集装箱
- DatagramSocket
- 发送或接收对象
- 作用:用来发送数据包或接收数据包
- 比喻:码头
- DatagramPacket类构造方法
- DatagramPacket(byte[] buf, int length, InetAddress address, int port)
- 创建发送端的数据包对象
- buf:字节数组,用来封装要发送的数据
- length:要发送内容的长度 单位是:字节
- address:接收端的IP地址对象
- port:接收端的端口号
- port:接收端的端口号
- 创建接收端的数据包对象
- 创建接收端的数据包对象
- length:能够接收内容的长度,单位:字节
- DatagramSocket类构造方法
- DatagramSocket()
- 创建发送端的Socket对象,随机生成一个端口号。
- DatagramSocket(int port)
- 根据端口号创建Socket对象
- DatagramSocket类成员方法
- void send(DatagramPacket dp) 发送数据包
- void receive(DatagramPacket dp) 接收数据包
2.1 UDP通信案例:
- 需求:学生的电脑的一个程序发送数据,一个程序接收数据,使用的学生本机的ip。
UDP发送端代码实现:
import java.io.IOException;
import java.net.*;
public class UDPsend {
public static void main(String[] args) throws Exception {
//定义字符串:要发送的内容
byte[] content = "我爱java".getBytes();
//创建数据包对象:用来封装要发送的数据
DatagramPacket dp = new DatagramPacket(content,content.length, InetAddress.getLocalHost(),8888);
//创建发送对象:Socket对象
DatagramSocket ds = new DatagramSocket();
//发送数据包
ds.send(dp);
//关闭Socket释放端口号
ds.close();
}
}
UDP接收端代码实现:
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/*
UDP接收端代码实现
*/
public class UDPReceive {
public static void main(String[] args) throws Exception{
//创建接收端的Socket
DatagramSocket ds = new DatagramSocket(8888);
//创建字节数组,存储接收到的内容
byte[] buf = new byte[1024];
//创建数据包对象,用来封装接收到的数据
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//接收数据包
ds.receive(dp);
//获得实际接收到的字节个数
int len = dp.getLength();
System.out.println("len="+len);
// 将字节数组转换为字符串输出
System.out.println(new String(buf,0,len));
// 获取发送端的IP地址
String sendIP = dp.getAddress().getHostAddress();
// 获取发送端的端口号
int sendPort = dp.getPort();
System.out.println("sendIP="+sendIP);
System.out.println("sendPort="+sendPort);
//关闭Socket释放端口号
ds.close();
}
}
3.1 TCP协议概述:
- TCP协议是面向连接的通信协议,即在传输数据前先在客户端和服务器端建立逻辑连接,然后再传输数据。它
提供了两台计算机之间可靠无差错的数据传输。TCP通信过程如下图所示:
- TCP协议的特点:(面试)
- 面向连接的协议
- 通过三次握手建立连接:形成数据传输通道。
- 通过四次挥手断开连接。
- 基于IO流进行数据传输。
- 传输数据大小没有限制。
- 速度慢但可靠的。
- TCP协议的使用场景:
- 文件上传下载
- 邮件发送和接收
- 远程登录
- TCP协议相当的两个类
- Socket:一个该类的对象就代表一个客户端程序
- ServerSocket:一个该类的对象就代表一个服务器端程序
- Socket类构造方法
- Socket(String host, int port)
- 根据服务器端IP地址和端口号创建客户端Socket对象
- host:服务器IP地址
- port:服务器端口号
- 注意:一旦执行该方法,就会立即连接指定的服务器,如果服务器没有开启,则连接失败抛出异常。
- Socket类成员方法:
- OutputStream getOutputStream(); 获得字节输出流对象
- InputStream getInputStream(); 获得字节输入流对象
- ServerSocket类概述:一个该类的对象就代表一个服务器端程序
- ServerSocket类构造方法:ServerSocket(int port)
- 根据端口号创建服务器端Socket对象, 相当于开启了一个服务器
- ServerSocket类成员方法:
- Socket accept() 等待客户端连接并获得与客户端相关的Socket对象
4.1 TCP通信案例:
客户端向服务器发送数据
- TCP客户端实现:
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/*
TCP客户端实现步骤:
*创建Socket对象指定服务器端IP地址和端口号
*调用Socket对象的getOutputStream方法获得字节输出流对象
* 调用字节输出流对象的Write方法往服务器端输出数据
* 调用Socket对象的getInputStream方法获得字节输入流对象
* 调用字节输入流对象的read方法读取服务器端返回的数据
* 关闭Socket对象断开连接
* 127.0.0.1 本机IP地址
*/
public class TCPClient {
public static void main(String[] args)throws Exception {
//创建客户端Socket对象:相当于开启一个客户端程序
Socket socket = new Socket("127.0.0.1",8888);
System.out.println(socket);
//获得字节输出流对象
OutputStream out = socket.getOutputStream();
//往服务器端输出数据
out.write("约吗?".getBytes());
//获得字节输入流对象
InputStream in = socket.getInputStream();
//定义字节数组:用来存储服务器返回的数据
byte[] buf = new byte[1024];
//读取服务器端返回的数据
int len =in.read(buf);
//输出服务器端返回的数据
System.out.println("len="+len);
System.out.println(new String(buf,0,len));
//关闭Socket对象
socket.close();
}
}
- TCP服务器端实现:
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/*
TCP服务器端代码实现步骤:
* 创建ServerSocket对象并指定端口号
* 调用ServiceSocket对象的accept方法等待客户端连接并获得与客户端相关的Socket对象
* 调用Socket对象的getInputStream方法获得字节输入流对象
* 调用字节输入流对象的read方法读取客户端发送的数据
* 调用Socket对象的getOutputStream方法获取字节输出流对象
* 调用字节输出流对象的write方法往客户端返回数据
* 调用close方法关闭Socket和ServerSocket对象
*/
public class TCPService {
public static void main(String[] args) throws Exception{
//根据端口号创建服务器端Socket对象
//相当于开启了一个服务器
ServerSocket serverSocket = new ServerSocket(8888);
//等待客户端连接并获得与客户端相关的Socket对象
Socket socket = serverSocket.accept();
System.out.println("-----------------");
//获得字节输入流对象
InputStream in = socket.getInputStream();
//定义字节数组:用来存储客户端发送的数据
byte[] buf = new byte[1024];
//读取客户端返回数据
int len = in.read(buf);
System.out.println("len="+len);
System.out.println(new String(buf,0,len));
//获得字节输出流对象
OutputStream out = socket.getOutputStream();
//往客户端输出数据
out.write("好的,约".getBytes());
// 关闭socket
socket.close();
// 关闭serverSocket(实际开发中一般不会关闭服务器)
serverSocket.close();
}
}
- 需求:使用TCP协议实现客户端和服务端互相发送消息。
- 客户端发送一条消息,服务器读取之后,返回一条消息给客户端,客户端读取服务器返回的消息之后,又发送一条消息...循环执行,直到输入exit。
- 消息内容通过键盘录入。
- 要求服务器端和客户端都使用字符流的方式发送和接收数据。
- 使用BufferedReader方法readLine()读取一行数据。
- 使用BufferedWrite方法的Write(“字符串的数据”)发送数据。
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/*
TCP通讯服务器端
*/
public class TCPServer {
public static void main(String[] args) {
System.out.println("服务器启动......");
try {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//创建服务器端Socket
ServerSocket serverSocket = new ServerSocket(9999);
//得到客户端对应的对象
Socket socket = serverSocket.accept();
//字符输入流
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//字符输出流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
while (true){
//接收对方的数据
System.out.println("客户端说:"+br.readLine());
System.out.println("我说:");
String words = sc.nextLine();
if ("exit".equals(words)) {
break;
}
//发送给对方
bw.write(words);
bw.newLine();
bw.flush();
}
br.close();
bw.close();
socket.close();
serverSocket.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
/*
TCP协议通讯客户端
*/
public class TCPClient {
public static void main(String[] args) {
try {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//根据服务器端的IP地址和端口号创建Socket对象
Socket socket = new Socket("127.0.0.1",9999);
//创建字符输入流对象
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//创建字符输出流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//输出数据
//创建键盘录入对象
while (true){
System.out.println("我说:");
//接收键盘录入的字符串
String words = sc.nextLine();
if("exit".equals(words)){
break;
}
//发送数据
bw.write(words);
//换行
bw.newLine();
//一定要flush
bw.flush();
System.out.println("收到对方的数据:"+br.readLine());
}
br.close();
bw.close();
//关闭Socket
socket.close();
}catch (Exception e){
e.printStackTrace();
}
}
}