所以我正在使用互联网上的指南学习UDP网络。我找到了一个指南,主要是复制/粘贴代码,并且它有效。那么我显然想要自己扩展。我正在尝试做一个简单的事情,它将为服务器提供客户端鼠标位置,然后服务器将向所有上限发送完全相同的消息。但由于某种原因,它可以完美地适用于0-100岁之间的任何地方然后停止。这是我的代码:
服务器:
public class Server implements Runnable {
boolean running = false;
long time;
InetAddress IPAddress;
int port;
public static void main(String[] args) throws Exception {
Thread th = new Thread(new Server());
th.start();
}
public Server() throws Exception {
DatagramSocket serverSocket = new DatagramSocket(9876);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
System.out.println("Server started");
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
IPAddress = receivePacket.getAddress();
port = receivePacket.getPort();
System.out.println("Client connected at " + IPAddress);
String send = "Connected!";
sendData = send.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
serverSocket.close();
time = System.nanoTime();
running = true;
}
public void run() {
int x = 0;
while(running) {
if(System.nanoTime() > time + 60/(1e9)) {
time = System.nanoTime();
try {
x++;
DatagramSocket serverSocket = new DatagramSocket(9876);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
System.out.println("Received message");
IPAddress = receivePacket.getAddress();
port = receivePacket.getPort();
String sentence = new String(receivePacket.getData());
System.out.println("RECEIVED " + sentence);
String capSentence = sentence.toUpperCase();
sendData = capSentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
System.out.println("Sent message.");
System.out.println(x);
serverSocket.close();
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
}
}
}
客户端:
public class Client implements Runnable {
boolean foundConnection = false;
boolean running = false;
long time;
public static void main(String[] args) throws Exception {
Thread th = new Thread(new Client());
th.start();
}
public Client() throws Exception {
time = System.nanoTime();
running = true;
}
public void run() {
while(running) {
if(System.nanoTime() > time + (60/1e9)) {
time = System.nanoTime();
try {
DatagramSocket clientSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("localhost");
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
String send = "Mouse is at " + mouse();
sendData = send.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
clientSocket.send(sendPacket);
System.out.println("Sent message.");
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
System.out.println("Received message.");
String modSentence = new String(receivePacket.getData());
System.out.println("FROM SERVER: " + modSentence);
clientSocket.close();
} catch(Exception e) {
System.out.println("Error");
}
}
}
}
public static Point mouse() {
return new Point((int)MouseInfo.getPointerInfo().getLocation().getX(),
(int)MouseInfo.getPointerInfo().getLocation().getY());
}
}
也许是因为它没有正确同步,服务器在客户端到达检查消息的代码部分之前发送消息?我不知道,因为我对此真的很陌生。我很想知道为什么会这样,以及如何解决它!对不起凌乱的代码,我是新手,并且编码一般。
答案 0 :(得分:0)
由于您不断打开和关闭服务器套接字,您很可能会遇到同步问题。这会在客户端的 send()和服务器的DatagramSocket创建之间创建race condition。如果客户端在服务器套接字初始化之前发送其数据包,则服务器不会收到它,只是等待它永远。这称为deadlock。
要避免此问题,只需打开服务器的套接字即可。初始化Server对象时打开它,服务器程序结束时关闭。这样,客户端发送的数据报将保存在套接字缓冲区中,直到服务器调用 receive()。
另外,服务器的构造函数和 run()方法有很多重复的代码。代码重复经常导致程序逻辑的不一致,因此也会导致错误。尽量避免复制粘贴代码。