UDP通信
- 特点:无连接,不可靠通信。通信效率高
- 不事先建立连接,数据按照包发,一包数据包含:自己的IP、程序端口,目的地址、程序端口和数据(限制在64KB内)等。
- Java提供了一个java.net.DatagramSocket类来实现UDP通信。
DatagramSocket:用于创建客户端、服务端
构造器 | 说明 |
---|---|
public DatagramSocket() | 创建客户端的Socket对象,系统会随机分配一个端口号 |
public DatagramSocket(int port) | 创建服务端的Socket对象,并指定端口号 |
方法 | 说明 |
---|---|
public void send(DatagramPacket dp) | 发送数据包 |
public void receive(DatagramPacket p) | 使用数据包接收数据 |
DatagramPacket:创建数据包
构造器 | 说明 |
---|---|
public DatagramPacket(byte[ ] buf,int length,InetAddress,int port) | 创建发出去的数据包对象 |
public DatagramPacket(byte[ ] buf,int length) | 创建用来接收数据的数据包 |
方法 | 说明 |
---|---|
public int getLength() | 获取数据包,时间接收到的字节个数 |
Client类
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Client {
public static void main(String[] args) throws Exception {
// 创建客户端对象
DatagramSocket socket = new DatagramSocket();
// 创建数据包对象要发出去的数据
/* public DatagramPacket(byte buf[],int length,InetAddress address,int port)
参数一:封装要发出去的数据
参数二:发送出去的数据大小(字节个数)
参数三:服务端的IP地址(找到服务端主机)
参数四:服务端程序的端口
*/
byte[] bytes = "我是客户端".getBytes();
DatagramPacket packet = new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),6666);
// 开始正式发送这个数据包的数据出去了
socket.send(packet);
System.out.println("客户端发送数据完毕");
socket.close();
}
}
Server类
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("———————服务端启动———————");
// 创建一个服务端对象 注册端口
DatagramSocket socket = new DatagramSocket(6666);
// 创建一个数据包对象,用于接收数据的
byte[] buffer = new byte[1024 * 64];
DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
// 开始正式使用数据包来接收客户端发来的数据
socket.receive(packet);
// 从字节数组中,把接收的数据之间打印出来
// 接收多少就倒出多少
// 获取本次数据包接收了多少数据
int len = packet.getLength();
String rs = new String(buffer,0,len);
System.out.println(rs);
System.out.println(packet.getAddress().getHostAddress());
System.out.println(packet.getPort());
socket.close(); // 释放资源
}
}
使用UDP通信实现:发送消息、接收消息
客户端实现步骤
- 创建DatagramSocket对象(客户端对象)
- 创建DatagramPacket对象封装需要发送的数据(数据包对象)
- 使用DatagramSocket对象的send方法,传入DatagramPacket对象
- 释放资源
服务端实现步骤
- 创建DatagramSocket对象指定端口(服务端对象)
- 创建DatagramPacket对象接收数据(数据包对象)
- 使用DatagramSocket对象的receive方法,传入DatagramPacket对象
- 释放资源
UDP通信多发多收
客户端实现步骤
- 创建DatagramSocket对象(客户端对象)
- 使用while死循环不断的接收用户的数据输入,如果用户输入exit则退出程序
- 如果用户输入的不是exit,包数据封装成DatagramPacket
- 使用DatagramSocket对象的send方法将数据包大小进行发送
- 释放资源
接收端实现步骤
- 创建DatagramSocket对象指定端口(服务端对象)
- 创建DatagramPacket对象接收数据(数据包对象)
- 使用DatagramSocket对象的receive方法,传入DatagramPacket对象
- 使用while死循环不断的进行第三步
Client类
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws Exception {
// 创建客户端对象
DatagramSocket socket = new DatagramSocket();
// 创建数据包对象要发出去的数据
/* public DatagramPacket(byte buf[],int length,InetAddress address,int port)
参数一:封装要发出去的数据
参数二:发送出去的数据大小(字节个数)
参数三:服务端的IP地址(找到服务端主机)
参数四:服务端程序的端口
*/
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请说:");
String msg = sc.next();
// 一旦发现用户输入了exit命令,就退出客户端
if (msg.equals("exit")){
System.out.println("退出成功");
socket.close();
break;
}
byte[] bytes = msg.getBytes();
DatagramPacket packet = new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),6666);
// 开始正式发送这个数据包的数据出去了
socket.send(packet);
}
}
}
Server类
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("———————服务端启动———————");
// 创建一个服务端对象 注册端口
DatagramSocket socket = new DatagramSocket(6666);
// 创建一个数据包对象,用于接收数据的
byte[] buffer = new byte[1024 * 64];
DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
while (true) {
// 开始正式使用数据包来接收客户端发来的数据
socket.receive(packet);
// 从字节数组中,把接收的数据之间打印出来
// 接收多少就倒出多少
// 获取本次数据包接收了多少数据
int len = packet.getLength();
String rs = new String(buffer,0,len);
System.out.println(rs);
System.out.println(packet.getAddress().getHostAddress());
System.out.println(packet.getPort());
}
}
}
TCP通信
- 特点:面向连接、可靠通信
- 通信双方事先会采用“三次握手”方式简历可靠连接,实现端到端的通信;底层能保证数据成功传给服务端
- Java提供了一个java.net.Socket类来实现TCP通信
TCP通信——客户端开发
- 客户端程序就是通过java.net包下的Socket类来实现的
构造器 | 说明 |
---|---|
public Socket(String host,int port) | 根据指定的服务器ip、端口号请求与服务端建立连接,连接通过,就获得了客户端socket |
方法 | 说明 |
---|---|
public OutputStream getOutputStream() | 获得字节输出流对象 |
public InputStream geInputStream() | 获得字节输入流对象 |
客户端发送消息
- 创建客户端的Socket对象,请求与服务端的连接
- 使用socket对象调用getOutputStream()方法得到字节输出流
- 使用字节输出流完毕数据的发送
- 释放资源:关闭socket管道
TCP通信——服务端程序的开发
- 服务端是通过java.net包下的ServerSocket类来实现的
ServerSpclet
构造器 | 说明 |
---|---|
public ServerSocket(int port) | 为服务端程序注册端口 |
方法 | 说明 |
---|---|
public Socket accept() | 阻塞等待客户端的连接请求,一旦与某个客户端成功连接,则返回服务端这边的Socket对象 |
服务端实现接收消息
- 创建ServerSocket对象,注册服务端端口
- 调用ServerSocket对象的accept()方法,等待客户端的连接,并得到Socket管道对象
- 通过Socket对象调用getInputStream()方法得到字节输入流、完成数据的接收
- 释放资源:关闭socket管道
Client类
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws Exception {
// 创建Socket对象,并同时请求与服务端程序的连接
Socket socket = new Socket("127.0.0.1",8888);
// 从socket通信管道中得到一个字节输出流,用来发送数据给服务端程序
OutputStream os = socket.getOutputStream();
// 把低级的字节输出流包装成数据输出流
DataOutputStream dos = new DataOutputStream(os);
// 开始写数据出去
dos.writeUTF("在吗?");
dos.close();
socket.close(); // 释放连接器资源
}
}
Server类
import java.io.DataInputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("------服务端启动成功------");
// 创建ServerSocket的对象,同时为服务端注册端口
ServerSocket serverSocket = new ServerSocket(8888);
// 使用serverSocket对象,调用一个accept方法,等待客户端连接请求
Socket socket = serverSocket.accept();
// 从socket通信管道中得到一个字节输入流
InputStream is = socket.getInputStream();
// 把原始的字节输入流包装成数据输入流
DataInputStream dis = new DataInputStream(is);
// 使用数据输入流读取客户端发送过来的消息
String rs = dis.readUTF();
System.out.println(rs);
// 获取客户端IP地址
System.out.println(socket.getRemoteSocketAddress());
dis.close();
socket.close();
}
}
TCP通信多发多收
- 使用TCP通信实现:多发多收消息
- 客户端使用死循环,让用户不断输入消息
- 服务端也使用死循环,控制服务端收完消息,继续等待接收下一个消息
Client类
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws Exception {
// 创建Socket对象,并同时请求与服务端程序的连接
Socket socket = new Socket("127.0.0.1",8888);
// 从socket通信管道中得到一个字节输出流,用来发送数据给服务端程序
OutputStream os = socket.getOutputStream();
// 把低级的字节输出流包装成数据输出流
DataOutputStream dos = new DataOutputStream(os);
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请说:");
String msg = sc.nextLine();
// 一旦发现用户输入了exit命令,就退出客户端
if (msg.equals("exit")){
System.out.println("退出成功");
dos.close();
socket.close();
break;
}
// 开始写数据出去
dos.writeUTF("在吗?");
dos.flush();
}
}
}
Server类
import java.io.DataInputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("------服务端启动成功------");
// 创建ServerSocket的对象,同时为服务端注册端口
ServerSocket serverSocket = new ServerSocket(8888);
// 使用serverSocket对象,调用一个accept方法,等待客户端连接请求
Socket socket = serverSocket.accept();
// 从socket通信管道中得到一个字节输入流
InputStream is = socket.getInputStream();
// 把原始的字节输入流包装成数据输入流
DataInputStream dis = new DataInputStream(is);
while (true) {
try {
// 使用数据输入流读取客户端发送过来的消息
String rs = dis.readUTF();
System.out.println(rs);
} catch (Exception e) {
System.out.println(socket.getRemoteSocketAddress() + "离线了");
dis.close();
socket.close();
break;
}
}
}
}