Есть два компьютера, A и B, каждый из которых ждет другого, чтобы сообщить ему, что он готов, когда они получают сообщение, что они начнут что-то делать.Java Socket не работает в локальной сети
public class SyncClientImpl implements SyncClient, Runnable {
private Socket s;
private String ipAddress;
private int port;
private boolean otherIsReady;
private Thread thread;
private OutputStream os;
private ObjectOutputStream oos;
public Thread getThread() {
return thread;
}
public void setThread(Thread thread) {
this.thread = thread;
}
public void start() {
thread = new Thread(this);
thread.start();
}
public boolean isOtherIsReady() {
return otherIsReady;
}
public void setOtherIsReady(boolean otherIsReady) {
this.otherIsReady = otherIsReady;
}
public Socket getS() {
if (s == null) {
try {
s = new Socket(ipAddress, port);
} catch (UnknownHostException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
return s;
}
public void setS(Socket s) {
this.s = s;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
@Override
public void send(Object o, int port, String ipAdrress) {
try {
os = this.getS().getOutputStream();
oos = new ObjectOutputStream(os);
oos.flush();
oos.writeObject(o);
oos.flush();
} catch (IOException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public void update() {
otherIsReady = true;
}
@Override
public void run() {
try {
while (!otherIsReady) {
try {
this.send("ready", port, ipAddress);
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
oos.close();
os.close();
s.close();
} catch (IOException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Этот первый класс отправляет сообщение «готов» к серверу, он прекратит это делать, пока кто-то еще не уведомит об этом. Класс, который уведомит его это одна:
public class SyncServerImpl implements SyncServer, Runnable {
private ServerSocket ss;
private Socket s;
private String ipAddress;
private int port;
private InputStream is;
private ObjectInputStream ois;
private boolean confirmReceived;
private Thread thread;
private transient List<Observer> list = new ArrayList<Observer>();
private Object lock;
public boolean isConfirmReceived() {
return confirmReceived;
}
public void setConfirmReceived(boolean confirmReceived) {
this.confirmReceived = confirmReceived;
}
@Override
public void setLock(Object lock) {
this.lock = lock;
}
public void start() {
thread = new Thread(this);
thread.start();
}
public Socket getS() {
if (s == null) {
try {
s = this.getSS().accept();
} catch (UnknownHostException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
return s;
}
public void setS(Socket s) {
this.s = s;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public ServerSocket getSS() {
if (ss == null) {
try {
ss = new ServerSocket(port);
} catch (IOException ex) {
Logger.getLogger(SyncServerImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
return ss;
}
public void setSS(ServerSocket ss) {
this.ss = ss;
}
@Override
public void addObserver(Observer observer) {
list.add(observer);
}
@Override
public void removeObserver(Observer observer) {
list.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : list) {
observer.update();
}
}
public void receive() {
try {
is = this.getS().getInputStream();
ois = new ObjectInputStream(is);
String to = (String) ois.readObject();
if (to.equalsIgnoreCase("ready")) {
synchronized (lock) {
confirmReceived = true;
this.notifyObservers();
lock.notifyAll();
}
System.out.println("packet received");
}
} catch (IOException ex) {
Logger.getLogger(SyncServerImpl.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(SyncServerImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public void run() {
try {
while (!confirmReceived) {
this.receive();
}
ois.close();
is.close();
s.close();
ss.close();
} catch (Exception ex) {
Logger.getLogger(SyncServerImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String args[]) {
final Object lock = new Object();
SyncServerImpl ss = new SyncServerImpl();
SyncClientImpl sc = new SyncClientImpl();
ss.setLock(lock);
ss.addObserver(sc);
ss.setPort(2002);
ss.start();
sc.setIpAddress("192.168.1.101");
sc.setPort(2002);
sc.start();
synchronized (lock) {
while (!ss.isConfirmReceived()) {
try {
lock.wait();
} catch (InterruptedException ex) {
}
}
}
System.out.println("Ok");
}
}
Этот сервер ожидает сообщение «готового», чтобы прибыть, когда он приходит он уведомляет об этом другом классе, который прекратит отправку пакетов, и уведомляет об этом основной поток, ожидающий блокировки. Он отлично работает на локальном хосте, но не в моей локальной сети. У меня есть mac и pc, если я начинаю основной метод сначала с компьютера, а затем с mac, я получаю эту ошибку (от mac, которая будет итерировать бесконечно).
sync.SyncClientImpl send
GRAVE: null
java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1864)
at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1773)
at java.io.ObjectOutputStream.<init>(ObjectOutputStream.java:229)
at tetris.logic.online.sync.SyncClientImpl.send(SyncClientImpl.java:87)
at tetris.logic.online.sync.SyncClientImpl.run(SyncClientImpl.java:106)
at java.lang.Thread.run(Thread.java:695)
в то время как на компьютере он сообщает мне, что соединение будет отказано (но это нормально, потому что он начинает первый)
Если я начну первым на макинтоше и на компьютере, я получаю эту ошибку (с компьютера), который будет итерацию до бесконечности тоже:
sync.SyncClientImpl send
GRAVE: null
java.net.SocketException: Software caused connection abort: socket write error
...
at tetris.logic.online.sync.SyncClientImpl.send(SyncClientImpl.java:87)
at tetris.logic.online.sync.SyncClientImpl.run(SyncClientImpl.java:106)
at java.lang.Thread.run(Thread.java:695)
Эта ошибка выглядит таким же, одного выше, но описано в другом порядке.
Кто-нибудь знает, что вызывает эту ошибку?
Не создавайте новый 'ObjectOutputStream' для каждой отправки. Создайте его один раз для жизни сокета. Тоже 'ObjectInputStream.' – EJP