JAVA UDP 多客户端响应
2020年3月4日
对于多客户端响应,不能使用TCP,TCP的话,因为要建立一个稳定的连接,所以就只能一对一,就好像之前JAVA TCP多线程那一文写的,哪怕Server端不管是咋实现,直接多线程或者是线程池,都是前一个socket断了后,后面一个才能直接续上,要是想实现多客户端同时连接的话,只能连接一个换一个端口,但是如果是UDP服务端的话,就不需要,因为UDP没有稳定的连接,都是直接发数据包,直接在服务端一个端口监听就好了,又因为每个数据包是会附带发送端的地址和端口,我们在回传的时候直接按照数据包里面的地址端口又发送回去就行了。
在这里我们需要做的就是如何储存数据包,这里需要注意的就是要用阻塞队列防止线程不安全。为了解决这个问题,我们可以使用LinkedBlockingQueue,在java里面我们进行值传递的时候如果是8个(还是6个,不记得了,就是int,double这种)一般变量和String这种变量的传递,是值传递,而其他变量,不管是class还是我们这里的Queue,都是地址传递,也就是说我们只要直接传递这个Queue,各个线程里面都是用的同一个Queue,然后就可以线程安全了。直接上代码吧
客户端
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] args) throws Exception {
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String userInput = null;
int serverPort = 6789;
DatagramSocket socket = new DatagramSocket();
while ((userInput = stdIn.readLine()) != null) {
DatagramPacket request = new DatagramPacket(userInput.getBytes(), userInput.getBytes().length,
InetAddress.getByName("127.0.0.1"), serverPort);
socket.send(request);
byte[] buffer = new byte[100];
DatagramPacket reply = new DatagramPacket(buffer, buffer.length);
socket.receive(reply);
System.out.println("The answer is " + new String(reply.getData()));
}
socket.close();
}
}
我们这用了buffer,可以循环输入。
服务端:
import java.net.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.io.*;
public class Server {
public static void main(String[] args) throws Exception {
DatagramSocket communication = new DatagramSocket(6789);
LinkedBlockingQueue<DatagramPacket> inputQueue = new LinkedBlockingQueue<DatagramPacket>();
LinkedBlockingQueue<DatagramPacket> responseQueue = new LinkedBlockingQueue<DatagramPacket>();
System.out.println("Server listening at 6789");
while (true) {
byte[] buffer = new byte[100];
DatagramPacket input = new DatagramPacket(buffer, buffer.length);
communication.receive(input);
inputQueue.add(input);
ProcessThread process = new ProcessThread(inputQueue, responseQueue);
process.start();
DatagramPacket tmp = responseQueue.poll(100, TimeUnit.MILLISECONDS);
communication.send(tmp);
}
}
}
class ProcessThread extends Thread {
private LinkedBlockingQueue<DatagramPacket> currentInput;
private LinkedBlockingQueue<DatagramPacket> currentResponse;
ProcessThread(LinkedBlockingQueue<DatagramPacket> a, LinkedBlockingQueue<DatagramPacket> b) {
currentInput = a;
currentResponse = b;
}
public void run() {
try {
DatagramPacket tmp = currentInput.poll(100, TimeUnit.MILLISECONDS);
byte[] data = tmp.getData();
String a = transfer(data);
currentResponse.put(new DatagramPacket(a.getBytes(), a.length(), tmp.getAddress(), tmp.getPort()));
} catch (Exception e) {
e.printStackTrace();
}
}
public String transfer(byte[] data) {
int first = 0;
int second = 0;
int answer = 0;
int index = 0;
String tmp = new String(data).trim();
if (tmp.contains("*")) {
index = tmp.indexOf("*");
first = Integer.parseInt(tmp.substring(0, index));
second = Integer.parseInt(tmp.substring(index + 1));
answer = first * second;
}
if (tmp.contains("/")) {
index = tmp.indexOf("/");
first = Integer.parseInt(tmp.substring(0, index));
second = Integer.parseInt(tmp.substring(index + 1));
answer = first / second;
}
if (tmp.contains("+")) {
index = tmp.indexOf("+");
first = Integer.parseInt(tmp.substring(0, index));
second = Integer.parseInt(tmp.substring(index + 1));
System.out.println(second);
answer = first + second;
}
if (tmp.contains("-")) {
index = tmp.indexOf("-");
first = Integer.parseInt(tmp.substring(0, index));
second = Integer.parseInt(tmp.substring(index + 1));
answer = first - second;
}
return Integer.toString(answer);
}
}
我们这为了验证是否匹配,我们发送的是一个计算表达式,客户端发送比如“100+200”,然后服务端返回计算的结果,这个很简单,就是切割string然后就直接计算,把结果放在返回的Queue里面,最后主线程从主线程里面每次取第一个元素就行了,然后我们这个数据处理线程每次取的是接受到的Queue的第一个元素。
Previous
最长有效括号(leetcode_32)
Newer