------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
网络编程的基础知识
网络中的数据传输是通过Socket套接字封装IP和端口来实现的
网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
udp和tcp的区别是
udp是不建立连接的协议,数据传输要打包,效率高但是不安全,不保证数据可以接收到
tcp是建立连接的协议,数据在传输前需要先建立连接通道,较安全,但是效率比较低
UDP协议的案例
需求:利用udp协议写一个简单的聊天室小程序,要求只需在同一个见面可以看到自己发送的信息即可
分析:
A:需要键盘录入数据
B:一个界面既可以发送信息也可以接收信息,说明同时要实现数据的发送和接收
用多线程实现
首先写两个线程类
把创建套接字对象放在无参构造的参数中实现
因为没有聊天室没有关闭按钮,所以暂时通过特定的字符串标识
创建发送数据的线程类
发送数据:
A:创建发送端Socket对象,此对象用来执行发送和接收数据报
udp不论是发送端还是接收端,Socket对象都是:
DatagramSocket() 此类表示用来发送和接收数据报包的套接字
B:创建数据,并把数据打包,此对象用来储存数据,是DatagramSocket的处理参数
数据报包对象是DatagramPacket,此类用来存放数据报,通过参数传递
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
存放的内容有:数据、其长度、远程主机的 IP 地址(对象)和远程主机的端口号
也就是说:目标地址其实是封装在了数据报对象中。
C:调用Socket对象的发送方法,发送数据报包
public void send(DatagramPacket p)
D:释放资源
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class SendThread implements Runnable {
// 创建套接字对象:通过参数传递过来套接字对象
private DatagramSocket ds;
public SendThread(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
// 创建数据:封装键盘录入对象数据对象
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 读取键盘录入的数据
String line = null;
try {
while ((line = br.readLine()) != null) {
//因为是循环,加入判断标识,退出循环,否则线程将一直开着
if(line.equals("886")){
break;
}
// 把读取的数据创建为要传递的数据
byte[] bys = line.getBytes();
// 创建数据包对象
DatagramPacket dp = new DatagramPacket(bys, bys.length,
InetAddress.getByName("127.0.0.1"), 22222);
//发送数据
ds.send(dp);
}
//释放资源
ds.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
创建接收数据的线程类
接收数据:
A:创建接收端Socket对象
DatagramSocket(int port)此对象要指明端口
B:创建一个数据包(接收容器)
DatagramPacket(byte[] buf, int length)
C:调用Socket对象的接收方法接收数据并把数据存入数据报包中
public void receive(DatagramPacket p)
此时只是获得了数据报包的对象,想要看到信息还要通过DatagramPacket的方法获得
D:解析数据包,并显示在控制台
DatagramPacket的常用方法有:
public InetAddress getAddress()获取发送该数据报包对象的ip
public byte[] getData():获取数据缓冲区
public int getLength():获取数据的实际长度
E:释放资源
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ReceiveThread implements Runnable {
// 创建套接字对象,由外界调用时传递
private DatagramSocket ds;
public ReceiveThread(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(ip + "发送的数据是:" + s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
测试
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDPNet {
public static void main(String[] args) throws SocketException {
//创建发送端和接收端的Socket对象
DatagramSocket dsSend = new DatagramSocket();
DatagramSocket dsReceive = new DatagramSocket(22222);
//创建Thread类对象
SendThread st = new SendThread(dsSend);
ReceiveThread rt = new ReceiveThread(dsReceive);
//创建线程对象
Thread t1 = new Thread(st);
Thread t2 = new Thread (rt);
//开启线程
t1.start();
t2.start();
}
}