我创建了一个服务器,它将在我的桌面上运行,以便从客户端发送和接收消息。客户端应用程序将在Android上运行。截至目前,两个程序都启动,客户端能够将初始连接发送到服务器。我的桌面通过路由器连接到互联网,我从路由器端口转发以接收信息。
服务器能够接收客户端发送的所有消息。但是,服务器无法响应。我快速检查了收到的数据包(服务器端),并说该数据包的ipaddress是我的路由器的IP。这是否意味着我将无法发送响应,因为我的所有数据包都会将其IP更改为路由器的本地地址(因为端口转发)?
我发布下面的一些代码,虽然我不确定它会有所帮助。非常感谢您的评论。
服务器:
public class QuoteServerThread extends Thread {
protected DatagramSocket socket = null;
DatagramPacket dgp = null;
protected boolean running = true;
ArrayList<ConnectedUser> users = new ArrayList<>();
String state;
int port;
int userId;
public QuoteServerThread(String name, String state) throws IOException {
super(name);
port = 4445;
userId = 1;
socket = new DatagramSocket(port);
this.state = state;
this.state = "listening";
System.out.println("Server Socket is now listening on port: " + port);
}
public void run() {
while (running) {
try {
byte[] buf = new byte[256];
// receive request
final DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
if(packet.getData() == null){
System.out.println(packet.getData());
return;
}
else{
System.out.println(packet.getData());
}
dgp = packet;
String message = new String(packet.getData(), 0, packet.getLength());
if(state.equals("listening")) {
if(message.contains("newUser")){
ConnectedUser newUser = new ConnectedUser(userId, socket);
users.add(newUser);
System.out.println("connected users: " + users.size());
String msg = "ID/" + userId;
InetAddress IPAddress = packet.getAddress();
int _port = packet.getPort();
System.out.println(IPAddress + "," + _port);
DatagramPacket out = new DatagramPacket(msg.getBytes(), msg.length(), IPAddress, _port);
socket.send(out);
userId++;
}
else if(message.contains("ID/")){
String receivedMessage[] = message.split("/");
System.out.println(receivedMessage[0] + ", " + receivedMessage[1] + ", " + receivedMessage[2]);
}
else{
System.out.println(message);
}
}
} catch (IOException e) {
e.printStackTrace();
running = false;
}
}
socket.close();
}
}
客户端:
public class QuoteServerThread extends Thread {
protected DatagramSocket socket = null;
protected boolean running = true;
TextView chatWindow;
TextView notification;
EditText chatBox;
MainActivity ma;
ScrollView sv;
public QuoteServerThread(MainActivity ma, TextView chatWindow, EditText chatBox, ScrollView sv, TextView notification) throws IOException {
this("QuoteServerThread");
this.ma = ma;
this.chatWindow = chatWindow;
this.sv = sv;
this.chatBox = chatBox;
this.notification = notification;
}
public QuoteServerThread(String name) throws IOException {
super(name);
socket = new DatagramSocket();
}
public void run() {
while (running) {
try {
byte[] buf = new byte[256];
// receive request
final DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
if(packet.getData() == null){
System.out.println("data was null!");
return;
}
String message = new String(packet.getData(), 0, packet.getLength());
final String notif = message;
notification.post(new Runnable() {
public void run() {
notification.setText("server " + "__msg: " + notif);
}
});
if(ma.state.equals("connected")) {
final String chatText = chatWindow.getText().toString() + "\n" + "Sender: " + message;
chatWindow.post(new Runnable() {
public void run() {
chatWindow.setText(chatText);
sv.post(new Runnable() {
public void run() {
sv.fullScroll(View.FOCUS_DOWN);
chatBox.post(new Runnable() {
public void run() {
chatBox.requestFocus();
}
});
}
});
}
});
}
else if(ma.state.equals("waitingconnection")){
String msgSplit[];
if(message.contains("ID/")){
msgSplit = message.split("/");
final String id = msgSplit[1];
ma.clientID = Integer.getInteger(id);
notification.post(new Runnable() {
public void run() {
notification.setText("connected to server " + "__msg: " + id);
ma.state = "connected";
}
});
}
}
} catch (IOException e) {
e.printStackTrace();
running = false;
}
}
socket.close();
}
}
这里唯一的问题是客户没有收到回复。再次说明问题,我相信我的路由器上的端口转发正在将数据包地址更改为其本地ipaddress(我的手机正在从移动网络发送)。关于如何解决这个问题的任何想法?
答案 0 :(得分:0)
我认为您正在看到网络地址转换(NAT)和端口转发的影响。从Android客户端的角度来看,它正在与您的路由器进行通信。然后,您的路由器而不是处理消息本身会将处理卸载到您的服务器(端口转发)。
在您的服务器上,您会看到目标地址。由于您的Android客户端正在与您的路由器通信,因此您看到的目标IP地址是路由器的IP地址。
如果您想回复,您应该采取数据报的源地址并将回复发送回该地址。当数据报通过带有NAT的路由器时,它会将源地址更改为路由器的地址。
答案 1 :(得分:0)
上面的问题是由于我在后台运行的代码。发送消息时,我使用的是名为MsgSender的类。但是,MsgSender正在创建一个新套接字并发送数据。发送数据后,它关闭了套接字,不再监听服务器的响应。
为了解决这个问题,我共享了一个打开的套接字,并通过单个套接字发送所有数据,以便它可以侦听返回的任何信息。
请确保在发送信息时,如果您需要侦听响应,则必须通过发送的套接字进行监听。如果您不需要侦听要发送的数据的响应,则可以关闭套接字。