UDP
特点:不建立连接;将数据源和目的封装成数据包中;
涉及类 DatagramSocket与DatagramPacket
public class DatagramSocket extends Object 描述:此类表示用来发送和接收数据报包的套接字。在 DatagramSocket 上总是启用 UDP 广播发送。
- 构造方法
- public DatagramSocket():构造数据报套接字并将其绑定到本地主机上任何可用的端口。
- public DatagramSocket(SocketAddress bindaddr):创建数据报套接字,将其绑定到指定的本地套接字地址。
- public DatagramSocket(int port):创建数据报套接字并将其绑定到本地主机上的指定端口。
- public DatagramSocket(int port, InetAddress laddr):创建数据报套接字,将其绑定到指定的本地地址。
- 常用方法
- public void send(DatagramPacket p):从此套接字发送数据报包。
- public void receive(DatagramPacket p):从此套接字接收数据报包。
public final class DatagramPacket extends Object 描述:此类表示数据报包。数据报包用来实现无连接包投递服务。
- 构造方法
- public DatagramPacket(byte[] buf, int length):构造 DatagramPacket,用来接收长度为 length 的数据包。
- public DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port):构造数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号。
- public DatagramPacket(byte[] buf, int offset, int length, SocketAddress address):构造数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号。
- public DatagramPacket(byte[] buf, int length, InetAddress address, int port):构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
- public DatagramPacket(byte[] buf, int length, SocketAddress address):构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
- 常用方法
- public InetAddress getAddress():获取数据报将要发往该机器或者是从该机器接收的 InetAddress 地址(通常为 IP 地址)。
- public SocketAddress getSocketAddress():获取要将此包发送到的或发出此数据报的远程主机的 SocketAddress(通常为 IP 地址 + 端口号)。
- public byte[] getData():返回数据缓冲区。接收到的或将要发送的数据从缓冲区中的偏移量 offset 处开始,持续 length 长度。
client发送端思路
- 建立udp的socket服务。
- 将要发送的数据封装成数据包。
- 通过udp的socket服务,将数据包发送出。
- 关闭资源。
client发送端代码
public class UdpClientDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();
byte[] bys = "hello,udp,我来了".getBytes();
int length = bys.length;
InetAddress address = InetAddress.getByName("192.168.0.106");
int port = 10086;
DatagramPacket dp = new DatagramPacket(bys, length, address, port);
ds.send(dp);
ds.close();
}
}
server接收端思路
- 建立udp的socket服务。
- 通过receive方法接收数据。
- 将收到的数据存储到数据包对象中。
- 通过数据包对象的功能来完成对接收到数据进行解析。
- 可以对资源进行关闭。
server接收端代码
public class UdpServerDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(10086);
byte[] bys = new byte[1024];
int length = bys.length;
DatagramPacket dp = new DatagramPacket(bys, length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
byte[] bys2 = dp.getData();
int len = dp.getLength();
String s = new String(bys2, 0, len);
System.out.println(ip + "传递的数据是:" + s);
ds.close();
}
}
运行服务端后,ds.receive(dp);该方法会一直阻塞等待数据。当客户端运行后,服务端打印“192.168.0.106传递的数据是:hello,udp,我来了”结束。
UDP案例
案例一
客户端:从键盘录入数据进行发送,如果输入的是886那么客户端就结束输入数据。 服务端:一直输出客户端发来的数据。
客户端-UdpClientDemo:
public class UdpClientDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line = br.readLine()) != null) {
if ("886".equals(line)) {
break;
}
byte[] bys = line.getBytes();
DatagramPacket dp = new DatagramPacket(bys, bys.length,
InetAddress.getByName("192.168.0.255"), 12345);
ds.send(dp);
}
ds.close();
}
}
服务端-UdpServerDemo:
public class UdpServerDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(12345);
while (true) {
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
String s = new String(dp.getData(), 0, dp.getLength());
System.out.println("from " + ip + " data is : " + s);
}
}
}
上述 DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName(“192.168.0.255”), 12345);中,192.168.0.255为广播地址,该网段所有主机均可接收。
案例二
发送和接收程序分别用线程进行封装,完成一个UDP的聊天程序。
客户端-UdpClientDemo
public class UdpClientDemo implements Runnable{
public DatagramSocket ds;
public UdpClientDemo(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
String line = null;
while ((line = br.readLine()) != null) {
if ("886".equals(line)) {
break;
}
byte[] bys = line.getBytes();
DatagramPacket dp = new DatagramPacket(bys, bys.length,
InetAddress.getByName("192.168.0.255"), 12306);
ds.send(dp);
}
ds.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务端-UdpServerDemo
public class UdpServerDemo implements Runnable {
public DatagramSocket ds;
public UdpServerDemo(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
while (true) {
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
String s = new String(dp.getData(), 0, dp.getLength());
System.out.println("from " + ip + " data is : " + s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
聊天室:
public class ChatRoom {
public static void main(String[] args) throws IOException {
DatagramSocket dsSend = new DatagramSocket();
DatagramSocket dsReceive = new DatagramSocket(12306);
UdpClientDemo client = new UdpClientDemo(dsSend);
UdpServerDemo server = new UdpServerDemo(dsReceive);
Thread t1 = new Thread(client);
Thread t2 = new Thread(server);
t1.start();
t2.start();
}
}
TCP
特点:建立连接;形成传输数据的通道,在连接中进行大数据量传输;
涉及类Socket和ServerSocket
public class Socket extends Object 描述:此类实现客户端套接字。
- 构造函数
- public Socket(String host, int port):创建一个流套接字并将其连接到指定主机上的指定端口号。
- host - 主机名,或者为 null,表示回送地址。
- port - 端口号。
- public Socket(InetAddress address, int port):创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
- address - IP 地址。
- port - 端口号。
- public Socket(String host, int port, InetAddress localAddr, int localPort):创建一个套接字并将其连接到指定远程主机上的指定远程端口。
- host - 远程主机名,或者为 null,表示回送地址。
- port - 远程端口
- localAddr - 要将套接字绑定到的本地地址
- localPort - 要将套接字绑定到的本地端口
- public Socket(InetAddress address, int port, InetAddress localAddr, int localPort):创建一个套接字并将其连接到指定远程地址上的指定远程端口。
- address - 远程地址
- port - 远程端口
- localAddr - 要将套接字绑定到的本地地址
- localPort - 要将套接字绑定到的本地端口
- 常用方法
- public void connect(SocketAddress endpoint):将此套接字连接到服务器。
- public SocketChannel getChannel():返回与此数据报套接字关联的唯一 SocketChannel 对象(如果有)。
- public InputStream getInputStream():返回此套接字的输入流。
- public OutputStream getOutputStream():返回此套接字的输出流。
- public void close():关闭此套接字。
public class ServerSocket extends Object 描述:此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。
- 构造函数
- public ServerSocket(int port):创建绑定到特定端口的服务器套接字。
- public ServerSocket(int port, int backlog, InetAddress bindAddr):使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。
- 常用方法
- public Socket accept():侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
- public void close():关闭此套接字。
- public ServerSocketChannel getChannel():返回与此套接字关联的唯一 ServerSocketChannel 对象(如果有)。
client发送端思路
- 建立客户端的socket服务,并明确要连接的服务器。
- 如果连接建立成功,就表明已经建立了数据传输的通道。就可以在该通道通过IO进行数据的读取和写入。该通道称为Socket流,Socket流中既有读取流,也有写入流。
- 通过Socket对象的方法,获取读取流、写入流。
- 通过流对象可以对数据进行传输。
- 如果传输数据完毕,关闭资源。
client发送端代码
public class TcpClientDemo {
public static void main(String[] args) throws IOException {
Socket s = new Socket("192.168.0.106", 22222);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter printWriter = new PrintWriter(s.getOutputStream(), true);
String line = null;
while ((line = br.readLine()) != null) {
if ("886".equals(line)) {
break;
}
printWriter.println(line);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(s.getInputStream()));
String readLine = bufferedReader.readLine();
System.out.println("接收数据:" + readLine);
}
s.close();
}
}
server接收端思路
- 建立服务器端的socket服务,绑定一个端口。
- 通过accept方法获取客户端对象,再通过获取到的客户端对象的流和客户端进行通信。
- 通过客户端的获取流对象的方法,读取数据或者写入数据。
- 如果服务完成,需要关闭客户端,然后关闭服务器。但是,一般会关闭客户端,不会关闭服务器,因为服务端是一直提供服务的。
server接收端代码
public class TcpServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(22222);
Socket s = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(s.getInetAddress().getHostAddress() + "---" + line);
PrintWriter printWriter = new PrintWriter(s.getOutputStream(), true);
printWriter.println("服务器响应数据" + line);
}
s.close();
}
}
先启动服务端,再启动客户端。 111 接收数据:服务器响应数据111 22 接收数据:服务器响应数据22 886
TCP案例
|