나는 주로 UDP와 컴퓨터가 서로 이야기하는 방법을 배우기 위해 간단한 Java 채팅 프로그램을 만들고 있습니다.다른 클라이언트가 서버에 보낼 때 UDP 서버를 클라이언트에 푸시하는 방법
지금까지 클라이언트에 연결할 클라이언트를 수신하도록 서버를 설정할 수 있었으며 서버를 통해 한 클라이언트에서 다른 클라이언트로 메시지를 리디렉션 할 수도 있습니다. 즉,
클라이언트 A -> 서버 -> 클라이언트 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();
}
}
클라이언트 측
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(); }
}
He 나는 동시에 두 개의 메인을 실행하려고하면 내가 오류입니다 재 (이 오류가 나에게 의미가 대부분의 경우, 난 그냥 듣고 클라이언트를하려면 어떻게 다른 모르겠어요) :
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 소켓을 청취 할 수 있습니다. - http://freecodetrips.blogspot.de/2009/06/java-socket-that-reuse-address.html 또는 MultiCastSocket을 사용하는 (ab) – zapl
에서 사용할 수있는'SO_REUSE_ADDR' 옵션이 있습니다. 간단하고 훌륭합니다. 나는 그것을 시험해 볼 것이고 만약 내가 일하게한다면 당신에게 알려줄 것입니다. 일반적으로 각 클라이언트 - 서버 관계에 대해 고유 한 포트를 보유하는 것이 좋습니다. 다시 한 번 감사드립니다! – Jona
@Jona 클라이언트가 동일한 시스템에서 실행되는지 또는 다른 시스템에서 실행되는지에 따라 다릅니다. 클라이언트가 다른 시스템에서 실행되는 경우. 클라이언트와 서버 소켓 모두 동일한 포트 일 수 있습니다. –