以下是我自己对UDP 一个发送者与一个接受者,多次咨询,双方互相发送的代码的优化,参考TCP的多线程
首先是Clinet项目
为一个发送者建立两个线程类,一个Send类,一个Receive类。用于发送和接收。
Send类
package com.gz.udp2;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Scanner;
public class Send implements Runnable{
private DatagramSocket ds;
private Scanner sc;
private String destIp;//目标ip
private int destPort;//目标端口号
private String role;//角色名称
private boolean flag=true;
public Send(DatagramSocket ds,String destIp,int destPort,String role) {
this.ds = ds;
this.destIp=destIp;
this.destPort=destPort;
this.role=role;
sc=new Scanner(System.in);
}
private String getMessage(){
return sc.next();
}
private void send(String str){
//发送时间
String date=new Date().toLocaleString();
str=date+" "+role+":"+str;
byte[] buf=str.getBytes();
try {
DatagramPacket dp=new DatagramPacket(buf,buf.length, InetAddress.getByName(destIp),destPort);
ds.send(dp);
} catch (IOException e) {
flag=false;
if(ds!=null) {
ds.close();
}
}
}
@Override
public void run() {
while(flag){
this.send(this.getMessage());
}
}
}
Receive类
package com.gz.udp2;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Scanner;
public class Receive implements Runnable{
private DatagramSocket ds;
private Scanner sc;
private boolean flag=true;
public Receive(DatagramSocket ds) {
this.ds = ds;
sc=new Scanner(System.in);
}
private String receive(){
String str="";
try {
byte [] buf=new byte[1024];//等待接收数据
DatagramPacket dp=new DatagramPacket(buf,buf.length);
ds.receive(dp);
str=new String(dp.getData(),0,dp.getLength());
} catch (IOException e) {
flag=false;
if(ds!=null){
ds.close();
}
}
return str;
}
@Override
public void run() {
while(flag){
System.out.println(this.receive());
}
}
}
Test1类,开启线程的类
package com.gz.udp2;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) throws IOException {
//DS
DatagramSocket ds=new DatagramSocket(9777);//自己的端口号
Send s=new Send(ds,"localhost",9888,"咨询者");
//目标ip,目标端口号,自己角色
Receive r=new Receive(ds);
new Thread(s).start();
new Thread(r).start();
}
}
对于接收者,也是拥有两个类,Send类和Receive类,及同样的开启线程类,只不过是端口号不同,角色不同。
接收者的Test2类
package com.gz.udp2;
import java.io.IOException;
import java.net.DatagramSocket;
public class Test2 {
public static void main(String[] args) throws IOException {
//DS
DatagramSocket ds=new DatagramSocket(9888);
Send s=new Send(ds,"localhost",9777,"客服人员");
//目标ip,目标端口号,自己角色
Receive r=new Receive(ds);
new Thread(s).start();
new Thread(r).start();
}
}
结果:成功实现了,客服多次回复:又优化加上了发送时间:
咨询者端:

客服端:

想让老师看一下我的代码还有哪里值得优化,还有一个问题,就是,单对单的时候,接收者在回复的时候可以获得发送者发送来的ip与端口号,但是我现在写成了多线程,并且在我的发送者与接收者的测试类里,ip跟端口号是单独指定的,也就是说,当线程开启之前,ip与端口号就固定下来了,下面的交互都是这两个ip与端口号之间的交互。我想问的是有办法像单对单那样,获取到上一个接收过来的数据来自的ip和端口号吗,这样的话就要找到上一个接收线程的DatagramPacket数据包dp,从dp能够获取到上一个发送端的ip及端口号,可是由于多线程,我编辑的逻辑是,每次接收和发送的方法都会创建新的DatagramPacket,当上一个线程调用发送方法以后,随着方法结束,dp数据包也会随之在内存中释放消失。所以,我觉得是完不成根据dp获取上一个发送端的ip及端口号的。因此这也是我的发送端和接收端都要重新制定ip及端口号的原因。
思考到这,(小总结******)我在想UDP是不是就是适合于两个人在通信的时候进行的交互,比如qq聊天,客服聊天,并且这两个人的聊天是指定两个人的单次会话的多次聊天。
而TCP适合群聊,中间的服务器可以将信息转发给其他人,也可以满足随时有人加入群聊,为随时加入群聊的客户端开启处理线程。
以上是我的思考,不知道有没有误解,想跟老师求证最后说的总结(带******号的)的正确性。
还有上面多线程的代码是否可以进一步优化,以及我对我的程序中发送端和接收端都要重新制定ip及端口号的理解是否正确。
还有就是UDP的单次会话的多线程如果真的实现是不是像我写的那样的,发送端和接收端都要重新制定ip及端口号。