实现基于UDP协议的的,两个进程(两个java程序)互相发送,并接受各自发送的数据的功能。
//First的main方法
public class First {
//定义表示发送方是否结束
public static boolean isSendOff=false;
//定义控制发送方结束的锁对象
public static Object flag=new Object();
public static void main(String[] args) throws SocketException, UnknownHostException {
//创建用于发送和接收的Stocket对象
DatagramSocket datagramSocket = new DatagramSocket(10010);
//创建用于发送数据的任务对象
//指定接收端的ip地址和端口号
String hostname="127.0.0.1";
int port =10086;
FirstSend firstSend = new FirstSend(datagramSocket, hostname, port);
//创建用于接收数据的任务对象
FirstRecesive firstRecesive = new FirstRecesive(datagramSocket);
//启动两个线程,分别运行发送和接收数据的任务
new Thread(firstSend).start();
new Thread(firstRecesive).start();
}
}
//First的发送线程FirstSend
public class FirstSend implements Runnable {
//创建发送方的Socket对象
private DatagramSocket datagramSocket;
//目标端Ip
private InetAddress targetIp;
//目标端端口号
private int targetPort;
//构造方法
public FirstSend(DatagramSocket datagramSocket, String targetIp, int targetPort) throws UnknownHostException {
this.datagramSocket = datagramSocket;
this.targetIp = InetAddress.getByName(targetIp);
this.targetPort = targetPort;
}
@Override
public void run() {
//键盘录入数据
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String data;
try {//当发送不为空时
while ((data=br.readLine())!=null) {
//调用方法,发送数据
sendData(data);
//当输入886时结束进程
if ("886".equals(data)){
synchronized (First.flag) {
First.isSendOff=true;//表示发送方结束了发送
break;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendData(String data) throws IOException {
byte[] byteData=data.getBytes();
DatagramPacket datagramPacket = new DatagramPacket(
byteData,0,byteData.length,targetIp,targetPort);
datagramSocket.send(datagramPacket);
}
}
//First的接收线程FirstReesive
public class FirstRecesive implements Runnable {
//创建接收方的Stocket对象
private DatagramSocket datagramSocket;
//构造接收方的方法
public FirstRecesive(DatagramSocket datagramSocket) {
this.datagramSocket = datagramSocket;
}
@Override
public void run() {
//创建接收数据的数据报包
byte[] byteBuffer=new byte[1024];
int off=0;
DatagramPacket recesivePacket = new DatagramPacket(byteBuffer,off,byteBuffer.length-off);
try {
while (true){
//接收数据,并将数据填充到接收数据的数据报包中
datagramSocket.receive(recesivePacket);
//从数据报包中获得数据并解析
String s=getDataAnalysis(recesivePacket);
if ("886".equals(s)){
break;
}
}
}catch (IOException e) {
e.printStackTrace();
}finally {
while (true){
synchronized (First.flag){
if (First.isSendOff){//如果发送方结束了
break;
}
//如果发送方没有结束,则等待100ms
try {
First.flag.wait(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
private String getDataAnalysis(DatagramPacket recesivePacket){
byte[] byteData=recesivePacket.getData();
int offset=recesivePacket.getOffset();
int len=recesivePacket.getLength();
//根据接收到的业务逻辑,分析获得数据
String s=new String(byteData,offset,len);
System.out.println("接收到了来自:"+recesivePacket.getAddress()+"--"+
recesivePacket.getPort()+"的数据:"+s);
return s;
}
}
//Second类和First一样只是接收和发送的端口号port与Ip地址不同(这里相同都是本机)
//Second的main方法
public class Second {
//定义表示发送方是否结束
public static boolean isSendOff=false;
//定义控制发送方结束的锁对象
public static Object flag=new Object();
public static void main(String[] args) throws SocketException, UnknownHostException {
//创建用于发送和接收的Stocket对象
DatagramSocket datagramSocket = new DatagramSocket(10086);
//创建用于发送数据的任务对象
//指定接收端的ip地址和端口号
String hostname="127.0.0.1";
int port =10010;
FirstSend firstSend = new FirstSend(datagramSocket, hostname, port);
//创建用于接收数据的任务对象
FirstRecesive firstRecesive = new FirstRecesive(datagramSocket);
//启动两个线程,分别运行发送和接收数据的任务
new Thread(firstSend).start();
new Thread(firstRecesive).start();
}
}
//Second的发送线程SenondSend
public class SecondSend implements Runnable{
//创建发送方的Socket对象
private DatagramSocket datagramSocket;
//目标端Ip
private InetAddress targetIp;
//目标端端口号
private int targetPort;
//构造方法
public SecondSend(DatagramSocket datagramSocket, String targetIp, int targetPort) throws UnknownHostException {
this.datagramSocket = datagramSocket;
this.targetIp = InetAddress.getByName(targetIp);
this.targetPort = targetPort;
}
@Override
public void run() {
//键盘录入数据
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String data;
try {//当发送不为空时
while ((data=br.readLine())!=null) {
//调用方法,发送数据
sendData(data);
//当输入886时结束进程
if ("886".equals(data)){
synchronized (Second.flag) {
Second.isSendOff=true;//表示发送方结束了发送
break;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendData(String data) throws IOException {
byte[] byteData=data.getBytes();
DatagramPacket datagramPacket = new DatagramPacket(
byteData,0,byteData.length,targetIp,targetPort);
datagramSocket.send(datagramPacket);
}
}
//Second的接收线程SecondRecesive
public class SecondRecesive implements Runnable {
//创建接收方的Stocket对象
private DatagramSocket datagramSocket;
//构造接收方的方法
public SecondRecesive(DatagramSocket datagramSocket) {
this.datagramSocket = datagramSocket;
}
@Override
public void run() {
//创建接收数据的数据报包
byte[] byteBuffer=new byte[1024];
int off=0;
DatagramPacket recesivePacket = new DatagramPacket(byteBuffer,off,byteBuffer.length-off);
try {
while (true){
//接收数据,并将数据填充到接收数据的数据报包中
datagramSocket.receive(recesivePacket);
//从数据报包中获得数据并解析
String s=getDataAnalysis(recesivePacket);
if ("886".equals(s)){
break;
}
}
}catch (IOException e) {
e.printStackTrace();
}finally {
while (true){
synchronized (Second.flag){
if (Second.isSendOff){//如果发送方结束了
break;
}
//如果发送方没有结束,则等待100ms
try {
Second.flag.wait(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
private String getDataAnalysis(DatagramPacket recesivePacket){
byte[] byteData=recesivePacket.getData();
int offset=recesivePacket.getOffset();
int len=recesivePacket.getLength();
//根据接收到的业务逻辑,分析获得数据
String s=new String(byteData,offset,len);
System.out.println("接收到了来自:"+recesivePacket.getAddress()+"--"+
recesivePacket.getPort()+"的数据:"+s);
return s;
}
}
思路:根据UDP的传输过程一步一步实现,其中利用了锁对象完成了线程的同步,利用发送标志判断是否发送完毕以便于结束会话.