有三个部分,服务器端,PC的客户端A和Android的客户端B.
逻辑是:
1.当客户端A和B连接到服务器时,他们将被通知另一个人的IP和端口
2.然后A将为B打一个洞并告诉服务器它已准备好从B接收。
3.服务器将告诉B A准备就绪
4.然后B将发送消息给A.
这只是一个简单的测试,测试环境是:
1.服务器有公共IP和端口
2.客户端A和客户端B处于不同的NAT
以下代码无效。两个对等方无法相互通信。如何让两个同行沟通?我会很感激你的每一条建议。
[编辑]
谢谢,@ kha。我第一次在这里发帖。我会详细说明这个过程
1. 3个部分也不例外。我没有错误。
2.两个客户端可以连接到服务器并从服务器接收另一个IP和端口
3.我关闭了Windows的防火墙。对于Android,我不知道该怎么做。
这两个客户只是无法沟通,没有任何其他例外
我是P2P的新手,所以我想找到更多帮助。
服务器端代码:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class Main {
static EndPoint endPoint;
static EndPoint endPoint2;
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) {
try {
DatagramSocket server = new DatagramSocket(5050);
boolean isSend = false;
while (true) {
System.out.println("start receiving...");
EndPoint ep = receiveMessage(server);
if (endPoint == null) {
System.out.println("endPoint initialized");
endPoint = ep;
} else if (endPoint2 == null) {
System.out.println("endPoint2 initialized");
endPoint2 = ep;
} else {
if (!isSend) {//when A and B all connect to server, they will be notified another's ip and port
isSend = true;
System.out.println("send to each other");
sendEndPointMessage(server, endPoint, endPoint2);
sendEndPointMessage(server, endPoint2, endPoint);
} else {
if ("5".equals(ep.message)) {// client A is ready
System.out.println("client A is ready");
sendMessage(server, "6", endPoint2);// send B message that A is reay
}
}
}
}
} catch (SocketException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void sendEndPointMessage(DatagramSocket server, EndPoint epReceive, EndPoint epContent) {
try {
String sendStr = epContent.host + ";" + epContent.port;
byte[] sendBuf = sendStr.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, epReceive.addr, epReceive.port);
server.send(sendPacket);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void sendMessage(DatagramSocket server, String msg, EndPoint ep) {
try {
byte[] sendBuf = msg.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, ep.addr, ep.port);
server.send(sendPacket);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private static EndPoint receiveMessage(DatagramSocket server) {
try {
byte[] recvBuf = new byte[1024];
DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length);
server.receive(recvPacket);
String recvStr = new String(recvPacket.getData(), 0, recvPacket.getLength());
int port = recvPacket.getPort();
InetAddress addr = recvPacket.getAddress();
System.out.println("EndPoint: host:" + recvPacket.getAddress() + ", port:" + port + ", message:" + recvStr);
EndPoint endPoint = new EndPoint(addr, port, recvStr);
return endPoint;
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
static class EndPoint {
InetAddress addr;
String host;
int port;
String message;
public EndPoint(String host, int port, String message) {
this.host = host;
this.port = port;
this.message = message;
try {
addr = InetAddress.getByName(host);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public EndPoint(InetAddress host, int port, String message) {
this.host = host.getHostAddress();
this.port = port;
this.message = message;
addr = host;
}
}
}
PC的客户端A:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class Main {
public static String serverAddr = "xxx.xxx.xxx.xx";
public static int serverPort = 5050;
public static String peerIP;
public static int peerPort;
/**
* @param args
*/
public static void main(String[] args) {
try {
final DatagramSocket client = new DatagramSocket();
sendMessage(client, "1", serverAddr, serverPort);
while (true) {
System.out.println("start receiving...");
String recvStr = receiveMessage(client);
if ("3".equals(recvStr)) {
sendMessage(client, "4", peerIP, peerPort);
} else {
String[] peer = recvStr.split(";");
if (peer.length > 1) {// received peer ip and port
peerIP = peer[0];
peerPort = Integer.parseInt(peer[1]);
sendMessage(client, "4", peerIP, peerPort);//punch a hole for client B
sendMessage(client, "5", serverAddr, serverPort);//tell server I am ready
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
sendMessage(client, "4", peerIP, peerPort);//keep punch a hole for client B
sendMessage(client, "5", serverAddr, serverPort);//keep telling server I am ready
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
} else {
if ("7".equals(recvStr)) {// received from client B
sendMessage(client, "got from android", peerIP, peerPort);
}
}
}
}
} catch (SocketException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private static String receiveMessage(final DatagramSocket client) {
try {
byte[] recvBuf = new byte[1024];
DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length);
client.receive(recvPacket);
String recvStr = new String(recvPacket.getData(), 0, recvPacket.getLength());
String ip = recvPacket.getAddress().getHostAddress();
int port = recvPacket.getPort();
System.out.println("received from: host:" + ip + ", port:" + port + ", content:" + recvStr);
return recvStr;
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static void sendMessage(final DatagramSocket client, String sendStr, String ip, int port) {
try {
System.out.println("send out: host:" + ip + ", port: " + port + ", message:" + sendStr);
byte[] sendBuf;
sendBuf = sendStr.getBytes();
InetAddress addr = InetAddress.getByName(ip);
DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, addr, port);
client.send(sendPacket);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Android的客户端B:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
public class MainActivity extends Activity {
public String serverAddr = "xxx.xxx.xxx.xx";
public int serverPort = 5050;
public String peerIP;
public int peerPort;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.connectServer).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
connectServer();
}
}).start();
}
});
}
private void connectServer() {
try {
DatagramSocket client = new DatagramSocket();
sendMessage(client, "2", serverAddr, serverPort);
while (true) {
System.out.println("start receiving...");
String recvStr = receiveMessage(client);
String[] peer = recvStr.split(";");
if (peer.length > 1) {// received peer ip and port
peerIP = peer[0];
peerPort = Integer.parseInt(peer[1]);
} else {
if ("6".equals(recvStr)) {//received from server that client A is ready
sendMessage(client, "7", peerIP, peerPort); // send message to client A
}
}
}
} catch (SocketException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private String receiveMessage(DatagramSocket client) throws IOException {
try {
byte[] recvBuf = new byte[1024];
DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length);
client.receive(recvPacket);
String ip = recvPacket.getAddress().getHostAddress();
int port = recvPacket.getPort();
String recvStr = new String(recvPacket.getData(), 0, recvPacket.getLength());
System.out.println("received from: host:" + ip + ", port:" + port + ", content:" + recvStr);
return recvStr;
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void sendMessage(DatagramSocket client, String sendStr, String ip, int port) {
try {
System.out.println("send out: host:" + ip + ", port:" + port + ", mesasge:" + sendStr);
byte[] sendBuf;
sendBuf = sendStr.getBytes();
InetAddress addr = InetAddress.getByName(ip);
DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, addr, port);
client.send(sendPacket);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:0)
我还有一台服务器需要测试。并且从客户端B找到与服务器A和服务器B相同的端口,NAT有两个不同的端口 我的NAT是一个对称的NAPT。所以我认为这是两个同行无法沟通的根本原因 @KunjanThadani,你是对的。