我正在用java写一个聊天程序,我已经被困了好几个小时了。这是我的等待客户端连接到服务器的类。
每次新客户端连接时,我都会创建一个新的ChatClient(String name, DatagramSocket serverSocket,InetAddress IPAddress, int port)
对象。
我的想法是每个ChatClient对象都在侦听套接字,并且当一个包从与ChatClient相同的IP发送时,它将处理它,否则什么也不做。
就像现在一样,当我只连接一个客户端时;客户端获取每2个包,然后在WaitForConnection()中运行run()获取其余的包。
所以我的问题是,是否有可能让多个线程在同一个DatagramSocket上监听而不会丢失(每个人都会发送所有内容)。如果有解决方案,怎么办?
private ArrayList<ChatClient> clients;
private DatagramSocket serverSocket;
private boolean running;
public WaitForConnection() {
running = true;
clients = new ArrayList<ChatClient>();
try {
serverSocket = new DatagramSocket(ChatServer.port);
} catch (SocketException e) {
System.out
.println("Couldn't open socket. Port might alreadybe in use");
e.printStackTrace();
}
try {
serverSocket.setReuseAddress(true);
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
while (running) {
for (ChatClient ch : clients) {
System.out.println(ch.toString());
}
byte[] handShake = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(handShake,
handShake.length);
try {
serverSocket.receive(receivePacket);
} catch (IOException e) {
System.out.println("Waiting for connections error");
e.printStackTrace();
}
String connect = new String(receivePacket.getData());
System.out.println(connect);
InetAddress IPAddress = receivePacket.getAddress();
// if connect == "OPEN_CONNECTION" -> new client want to connect.
if (connect.contains("openconnection")) {
int port = receivePacket.getPort();
try {
ChatClient chatClient = new ChatClient(
IPAddress.getHostName(), serverSocket, IPAddress,
port);
// Don't want double clients.
for (int i = 0; i < clients.size(); i++) {
if (clients.get(i).equals(chatClient)) {
clients.remove(i);
}
}
clients.add(chatClient);
} catch (IOException e) {
System.out.println("Couldn't connect to client");
e.printStackTrace();
}
}
}
}
}
如果你需要查看它,可以使用ChatClient代码。
public class ChatClient extends Thread {
private InetAddress IPAddress;
private DatagramSocket serverSocket;
private int port;
private String name;
public ChatClient(String name, DatagramSocket serverSocket,
InetAddress IPAddress, int port) throws IOException {
super(name);
this.name = name;
this.IPAddress = IPAddress;
this.serverSocket = serverSocket;
this.port = port;
byte[] confirmConnection = new byte[1024];
String connected = "Connection to server established";
confirmConnection = connected.getBytes();
serverSocket.send(new DatagramPacket(confirmConnection,
confirmConnection.length, IPAddress, port));
start();
}
public void run() {
while (true) {
byte[] message = new byte[1024];
DatagramPacket receivedPacket = new DatagramPacket(message,
message.length);
try {
serverSocket.receive(receivedPacket);
} catch (IOException e) {
System.out
.println("Something went wrong receiving data in ChatClient");
}
if (receivedPacket.getAddress().equals(IPAddress)) {
String connect = new String(receivedPacket.getData());
connect = connect.toUpperCase();
System.out.println(connect + "client side");
message = connect.getBytes();
try {
serverSocket.send(new DatagramPacket(message,
message.length, IPAddress, port));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
答案 0 :(得分:4)
多个线程可以从同一个DatagramSocket接收,但只有一个线程可以获取每个数据报。
我不明白为什么你认为你需要这个。
答案 1 :(得分:1)
技术上不可能,因为网络硬件只接收一次数据包。但是一旦读完,你总是可以在内存中复制它。在你的代码中基本上只做Arrays.copyOf(receivePacket)
对于更复杂的版本,您可以使用NIO包并使用Selector。这将允许您通过单个线程运行所有网络连接,该线程将数据读取并分发到处理线程。如果您有来自许多客户端的多个连接,那么可以节省额外的线程开销。