我正在学习一些UDP并且正在创建一个客户端 - 服务器 - 客户端聊天程序。
它的设置方式是服务器首先运行,并且始终在端口X上侦听来自客户端的一些命令。
另一方面,客户端如果要登录或发送消息,则在端口X上向服务器发送命令,但是它正在端口Y上侦听来自服务器的传入数据包。当然,服务器也在端口Y上发送消息。
如果客户端A登录(用户必须做的第一件事),服务器将接收客户端的用户名,然后根据收到的数据包获取客户端的IP,并将两者都存储在以用户名作为密钥的地图中。
当客户端B登录时,会发生相同的过程。现在,客户端A可以向客户端B发送消息(反之亦然),因为它们的用户名和IP都存储在服务器中。
当两个客户端都在同一台机器上时,一切正常,但是一旦我尝试在另一台机器上运行客户端B,似乎数据包永远不会到达服务器。没有错误,程序不会崩溃,但服务器永远不会收到任何错误。
我尝试了一堆不同的IP供客户端发送到 - 一个是我在命令行上运行'ipconfig'获得的,另一个来自google搜索“我的IP地址是什么?”,我从打印到控制台InetAddress.getLocalHost()获得的第三个IP - 所有这三个IP都不同,似乎都没有。
在两台机器上,我都进入防火墙并允许端口X和Y用于入站和出站活动的UDP连接。这似乎没有帮助。
这是我的服务器代码:
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, InetAddress.getLocalHost());
}
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);
//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[1] + 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
int add = 1;
packet = new DatagramPacket(buffer, buffer.length, nameIPTree.get(instructions[2]), PORT_NUMBER+add);
System.out.println("Sending packet from server to client at packet address: " + packet.getAddress());
//Send the packet
sock.send(packet);
System.out.println("Server: Sent result to Client: " + toUser);
}
}
catch (IOException /*| ClassNotFoundException | SQLException*/ e){
e.printStackTrace();
break;
}
}
System.out.println("Closing the socket");
sock.close();
}
}
客户代码:
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 - this is where the server is
InetAddress ipAddress = InetAddress.getByName("123.456.78.9");//here is where I tried the different IPs;
//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);
//I know these if statements do the same - it was for testing purposes
if(message.substring(0, 5).equals("LOGIN")){
System.out.println("Client: Logging in");
System.out.println("Packet's address is: " + packet.getAddress());
//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;
}
}
这是我的Main类中的客户端监听器:
public MainGUI() throws SocketException, UnknownHostException{
sock = new DatagramSocket(PORT_NUMBER+1, InetAddress.getLocalHost());
System.out.println("Client listening on ip: " + InetAddress.getLocalHost());
}
public void run(){
while(true){
try {
byte[] buffer = new byte[512];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
sock.receive(packet);
String fromUser = new String(packet.getData(), 0, packet.getLength());
//Parse data
String[] instructions = fromUser.split(separator);
txtAreaConvo.append(instructions[0] + ":\t" + instructions[1]+"\n\n");
} catch (IOException e) { e.printStackTrace(); }
}
}
此时的任何帮助都将狂野地赞赏!!!
提前致谢,
Jona的
答案 0 :(得分:2)
每当我进行套接字编程时,我的第一步是让数据包通信正常工作。我使用基本的客户端 - 服务器实现,只是来回发送" Hello World",以确保我可以单独运行所有内容(而不是localhost)。您可能希望从实施整个程序中退后一步,并尝试在继续之前使通信正常工作。这可能会显示您的错误所在。话虽如此,我会试着猜出你的问题所在:
如果您的客户端 - 服务器通信正在运行,那么在您更改为其他IP之前,我将不得不像您一样假设您提供了错误的IP地址/端口号。确保客户端正在发送到服务器正在侦听的端口X.我怀疑这不是你的问题;你的问题可能就是你所提供的IP。 whatismyip.com,会给你你的公共IP地址(如果你的客户端在不同的网络上你应该使用的IP地址),ifconfig将为你提供你的本地IP地址,即192.168.XX(你应该使用的IP地址,如果客户端使用相同的网络。)
总而言之,我会用我的第一个建议。退一步,在尝试解决总体目标之前,先进行基本的服务器 - 客户端通信。如果您需要一些基本的客户端 - 服务器程序,请查看Java Socket Programing Examples。一旦你完成这些工作,我会继续解决你的总体目标。这将帮助您缩小问题范围,并可能解决问题。