UDP
UDP协议的特点
- 面向无连接的协议
- 发送端只管发送,不确认对方是否能收到。
- 基于数据包进行数据传输。
- 发送数据的包的大小限制64KB以内
- 因为面向无连接,速度快,但是不可靠。会丢失数据!
UDP协议的使用场景:在线视频,网络语音等
UDP协议相关的两个类
DatagramPacket:数据包对象
作用:用来封装要发送或要接收的数据,比如:集装箱
DatagramSocket:发送对象
作用:用来发送或接收数据包,比如:码头
DatagramPacket类构造器
发送端:
创建发送端数据包对象:
new DatagramPacket(byte[] buf, int length, InetAddress address, int port)
- buf:要发送的内容,字节数组
- length:要发送内容的长度,单位是字节
- address:接收端的IP地址对象
- port:接收端的端口号
接收端:
创建接收端的数据包对象:
new DatagramPacket(byte[] buf, int length)
- buf:用来存储接收到内容
- length:能够接收内容的长度
DatagramPacket类常用方法
- int getLength() 获得实际接收到的字节个数
DatagramSocket类构造方法
- DatagramSocket() 创建发送端的Socket对象,系统会随机分配一个端口号。
- DatagramSocket(int port) 创建接收端的Socket对象并指定端口号
DatagramSocket类成员方法
- void send(DatagramPacket dp) 发送数据包
- void receive(DatagramPacket p) 接收数据包
客户端
public static void main(String[] args) {
seedMassage();
}
private static void seedMassage() {
System.out.println("客户端启动");
Scanner scanner = new Scanner(System.in);
String input = scanner.next();
byte[] send = input.getBytes();
DatagramPacket packet = null;
DatagramSocket socket = null;
try {
packet = new DatagramPacket(send,send.length,InetAddress.getLocalHost(),6666);
socket = new DatagramSocket(8888);
socket.send(packet);
// seedMassage();
} catch (Exception e) {
e.printStackTrace();
}finally {
socket.close();
}
}
服务端
public static void main(String[] args) {
DatagramPacket packet = null;
DatagramSocket socket = null;
byte[] receive = new byte[1024*64];//UDP最大传输量为64K
System.out.println("服务端启动");
try {
packet = new DatagramPacket(receive,receive.length);
socket = new DatagramSocket(6666);
while (true){
socket.receive(packet);
int dataLenght = packet.getLength();
System.out.println(new String(receive,0,dataLenght));
}
}catch (Exception e){
e.printStackTrace();
}
}
TCP
TCP/IP协议的特点
- 面向连接的协议
- 只能由客户端主动发送数据给服务器端,服务器端接收到数据之后,可以给客户端响应数据。
- 通过三次握手建立连接,连接成功形成数据传输通道。
- 通过四次挥手断开连接
- 基于IO流进行数据传输
- 传输数据大小没有限制
- 因为面向连接的协议,速度慢,但是是可靠的协议。
TCP协议的使用场景:文件上传和下载、邮件发送和接收、远程登录等
TCP协议相关的类
Socket
- 一个该类的对象就代表一个客户端程序。
ServerSocket
- 一个该类的对象就代表一个服务器端程序。
TCP通信也叫Socket网络编程,只要代码基于Socket开发,底层就是基于了可靠传输的
Socket类构造方法
- Socket(String host, int port)
根据ip地址字符串和端口号创建客户端Socket对象
注意事项:只要执行该方法,就会立即连接指定的服务器程序,如果连接不成功,则会抛出异常。
如果连接成功,则表示三次握手通过。
Socket类常用方法
- OutputStream getOutputStream(); 获得字节输出流对象
- InputStream getInputStream();获得字节输入流对象
客户端的开发流程:
- 客户端要请求于服务端的socket管道连接。
- 从socket通信管道中得到一个字节输出流
- 通过字节输出流给服务端写出数据。
服务端的开发流程:
- 注册端口。
- 接收客户端的Socket管道连接。
- 从socket通信管道中得到一个字节输入流。
- 从字节输入流中读取客户端发来的数据。
服务端
public class TCPService {
public static void main(String[] args) throws IOException {
System.out.println("服务端启动");
ServerSocket serverSocket = new ServerSocket(Contants.PORT);
Socket socket = null ;
try {
while (true){
socket = serverSocket.accept();
System.out.println(socket.getRemoteSocketAddress()+"来了,老弟!");
new SereverReaderThread(socket).start();
}
}catch (Exception e){
System.out.println(socket.getRemoteSocketAddress()+"下线了");
}
}
}
public class SereverReaderThread extends Thread {
private Socket socket ;
public SereverReaderThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
BufferedOutputStream bos = null ;
try {
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
bos = new BufferedOutputStream(new FileOutputStream(Contants.DEST_FILE+ UUID.randomUUID()+".jpg"));
byte[] bytes = new byte[1024];
int len ;
while ((len = bis.read(bytes)) != -1){
bos.write(bytes);
}
bos.flush();
// 服务端响应接收成功的结果!
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.println("图片传输完成!");
printStream.flush();
}catch (Exception e){
System.out.println(socket.getRemoteSocketAddress()+"下线了");
}finally {
try {
if (bos!=null)
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端
public class TCPClient {
public static void main(String[] args) throws Exception {
Socket socket = null;
try {
socket = new Socket(Contants.IP,Contants.PORT);
// PrintStream printStream = new PrintStream(socket.getOutputStream());
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(Contants.SRCFILE));
byte[] bytes = new byte[1024];
int len ;
while ((len = bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
bos.flush();
bis.close();
socket.shutdownOutput();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(br.readLine());
}catch (Exception e){
e.printStackTrace();
}
}
}