Я работаю над простой программой чата Java, в основном, чтобы узнать о UDP и о том, как компьютеры разговаривают друг с другом.Как заставить UDP-сервер нажимать на Клиент, когда другой клиент отправляет сервер
До сих пор мне удалось настроить сервер, чтобы прослушивать подключение к нему клиентов, и я даже могу перенаправить сообщения от одного клиента к другому, хотя сервер - то есть:
Client A -> сервер -> Client B
Я добрался до места, где сервер фактически посылает пакет (sock.send (пакетов)), но загвоздка в том, что клиенты не» действительно «знаю», чтобы слушать. Они просто знают, как отправить сервер.
Я попытался настроить run() для клиента, аналогично тому, что у меня есть с сервером, но как только я вытаскиваю двух клиентов, моя программа вылетает из-за того, что я пытаюсь прослушивать один и тот же порт.
код сервера (Просьба игнорировать весь материал сепаратора, это просто способ я использую для отправки различных частей информации в настоящее время):
package com.jona.chat.UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.sql.SQLException;
import java.util.TreeMap;
public class UDPServer extends Thread{
final int PORT_NUMBER = 4447;
private String separator = "~!~--//1337"; //IGNORE THIS
protected DatagramSocket sock = null;
private TreeMap<String,InetAddress> nameIPTree = new TreeMap<String,InetAddress>(); //IGNORE THIS
public static void main(String args[]) throws IOException{
UDPServer SERVER = new UDPServer();
//calls the run() method
SERVER.start();
}
public UDPServer() throws IOException{
sock = new DatagramSocket(PORT_NUMBER);
}
public void run(){
System.out.println("Waiting for Client");
while(true){
try{
//========================================================================================================
//Prepare the packet to receive data from client
//========================================================================================================
//Buffer (byte array) that will receive the client's data
byte[] buffer = new byte[512];
//Create a packet using the empty buffer and its length
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
//========================================================================================================
//Receive the packet from the client, execute the statement, and get the result
//========================================================================================================
//Receive the packet
sock.receive(packet);
System.out.println("Server: Received packet from Client");
//Extract the data
String fromUser = new String(packet.getData(), 0, packet.getLength());
//Parse data
String[] instructions = fromUser.split(separator); //IGNORE THIS
//Add UserName and IP to tree
if(instructions[0].equals("LOGIN")){
System.out.println("Logged in!");
nameIPTree.put(instructions[1], packet.getAddress());
run();
}
//Send message to recipient and upload to DB
else if(instructions[0].equals("MESSAGE")){
//Create a string composed of the sender and the message
String toUser = instructions[2] + separator + instructions[3];
//Store the string in the buffer
buffer = toUser.getBytes();
//Make a new packet with the buffer, its length, the RECEPIENT'S IP (retrieved from tree, hence receiving user HAS TO BE LOGGED IN)
//and the port number the server uses
packet = new DatagramPacket(buffer, buffer.length, nameIPTree.get(instructions[2]), PORT_NUMBER+1);
//Send the packet
sock.send(packet);
System.out.println("Server: Sent result to Client: " + toUser);
}
}
catch (IOException e){
e.printStackTrace();
break;
}
}
System.out.println("Closing the socket");
sock.close();
}
}
Client Side
public class UDPClient extends Thread{
final int PORT_NUMBER = 4447;
private String separator = "~!~--//1337";
public String TalkToServer(String message){
try{
//========================================================================================================
//Create a datagram socket
//========================================================================================================
DatagramSocket sock = new DatagramSocket();
//========================================================================================================
//Connect & Send to server
//========================================================================================================
//Create a byte array called buffer that will hold the instructions to be sent to the server
byte[] buffer = message.getBytes("UTF-8");
//Get the IP address to which the packet will be sent
InetAddress ipAddress = InetAddress.getByName("123.45.67");
//Create a datagram packet which is composed of the buffer (message), its length, the IP address,
//and the port (matches with server's listening port) to send the data on
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, ipAddress, PORT_NUMBER);
//same thing in both ifs, I know, I just wanted to see what it was doing
if(message.substring(0, 5).equals("LOGIN")){
System.out.println("Client: Logging in");
//Send the packet
sock.send(packet);
System.out.println("Client: Sent packet to Server\nSent: " + message);
sock.close();
return null;
}
if(message.substring(0, 7).equals("MESSAGE")){
System.out.println("Client: Sending message to server");
//Send the packet
sock.send(packet);
System.out.println("Client: Sent packet to Server\nSent: " + message);
sock.close();
return null;
}
}
catch(IOException e){System.out.print(e);}
return null;
}
}
И, наконец, , вот как я пытался заставить клиента слушать (это в моем основном классе):
public static void main(String[] args) throws SocketException{
MainGUI listener = new MainGUI();
listener.start();
...
public MainGUI() throws SocketException{
sock = new DatagramSocket(PORT_NUMBER+1);
}
public void run(){
byte[] buffer = new byte[512];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
try {
sock.receive(packet);
String fromUser = new String(packet.getData(), 0, packet.getLength());
//Parse data
String[] instructions = fromUser.split(separator);
System.out.println("Received message: " + instructions[1] + " from " + instructions[0]);
} catch (IOException e) { e.printStackTrace(); }
}
Он повторно это ошибка, я получаю, когда я пытаюсь запустить два Mains одновременно (эта ошибка имеет смысл для меня по большей части, я просто не знаю, что еще нужно сделать, чтобы получить клиент для прослушивания):
Exception in thread "main" java.net.BindException: Address already in use: Cannot bind
at java.net.DualStackPlainDatagramSocketImpl.socketBind(Native Method)
at java.net.DualStackPlainDatagramSocketImpl.bind0(Unknown Source)
at java.net.AbstractPlainDatagramSocketImpl.bind(Unknown Source)
at java.net.DatagramSocket.bind(Unknown Source)
at java.net.DatagramSocket.<init>(Unknown Source)
at java.net.DatagramSocket.<init>(Unknown Source)
at java.net.DatagramSocket.<init>(Unknown Source)
at com.jona.chat.UDP.UDPServer.<init>(UDPServer.java:28)
at com.jona.chat.UDP.UDPServer.main(UDPServer.java:20)
Заранее благодарим за помощь!
Вы можете хотя бы прослушивать сокеты UDP. - Существует опция SO_REUSE_ADDR, которая может использоваться либо по адресу http://freecodetrips.blogspot.de/2009/06/java-socket-that-reuse-address.html, либо по (ab) с использованием MultiCastSocket – zapl
. Это простой и блестящий. Я попробую и дам вам знать, буду ли я работать. Вообще говоря, эта хорошая практика - просто иметь уникальный порт для каждого отношения клиент-сервер? Еще раз спасибо! – Jona
@Jona Зависит от того, работают ли клиенты на той же машине или другой. Если клиенты работают на разных машинах. Вы можете использовать один и тот же порт для клиентских и серверных сокетов. –