PDA

View Full Version : Problemi con java.net


Lakaj
09-02-2007, 15:59
Ciao ragazzi, ho nuovamente problemi...
NetBeans 5.5 sputa fuori queste eccezioni, in un applicativo che usa java.net.*

java.net.BindException: Permission denied
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:359)
at java.net.ServerSocket.bind(ServerSocket.java:319)
at java.net.ServerSocket.<init>(ServerSocket.java:185)
at java.net.ServerSocket.<init>(ServerSocket.java:97)
at simserver.Interf1.<init>(Interf1.java:30)
at simserver.Main.main(Main.java:27)

Ora non so se è un fatto di porte non nattate del router dannazione...
Il codice è questo:

/*
* Main.java
*
* Created on 9 febbraio 2007, 9.50
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package simserver;
import java.io.*;
/**
*
* @author ale
*/
public class Main {

/** Creates a new instance of Main */
public Main() {
}

/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {
// TODO code application logic here
Interf1 interf=new Interf1(900);
interf.setVisible(true);
}
}
/*
* Mserver.java
*
* Created on 9 febbraio 2007, 9.50
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package simserver;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
/**
*
* @author ale
*/
public class Mserver extends JFrame implements Runnable {

protected Socket client;
private JLabel notifica;
Thread thr;
/** Creates a new instance of Mserver */
public Mserver(Socket skt) {
super(skt.getInetAddress().toString());
this.setVisible(true);
notifica=new JLabel("Arrivato nuovo client da "+ skt.getInetAddress());
client=skt;
}
public void init() {
thr=new Thread(this);
getContentPane().add(notifica);
pack();
}
public void start() {
thr.start();
}
public void run() {
try {
InputStream i=client.getInputStream();
OutputStream o=client.getOutputStream();
PrintStream p=new PrintStream(o);
p.println("Benvenuti");
p.println("Digitare HELP per lista servizi");
int x;
ByteArrayOutputStream command=new ByteArrayOutputStream();
String helpcommand=new String("HELP");
String quitcommand=new String("QUIT");
while((x=i.read())>-1) {
o.write(x);
if(x==13) {
p.println();
if(helpcommand.equalsIgnoreCase(command.toString()))
p.println("Il solo servizio disponibile è l'help");
else if(quitcommand.equalsIgnoreCase(command.toString())) {
p.println("BYE.");
try {
Thread.sleep(1000);
}
finally {
break;
}
}
else
p.println("Comando non disponibile.");
command.reset();
}
else if(x!=10)
command.write(x);
}
}
catch(IOException e) {
e.printStackTrace();
}
finally {
notifica.setText("Connessione chiusa con " + client.getInetAddress());
try {
client.close();
}
catch(IOException e) {
e.printStackTrace();
}
}
}
}
/*
* Interf1.java
*
* Created on 9 febbraio 2007, 10.42
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package simserver;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
/**
*
* @author ale
*/
public class Interf1 extends JFrame {

private JLabel message;
private JLabel attesa;
/** Creates a new instance of Interf1 */
public Interf1(int port) {
message=new JLabel("Server in partenza sulla porta " + port);
getContentPane().add(message);
pack();
try {
ServerSocket svr=new ServerSocket(port);
message.setText("Server partito sulla porta " + svr.getLocalPort());
Socket client;
attesa=new JLabel("");
getContentPane().add(attesa);
while(true) {
client=svr.accept();
attesa.setText("Richiesta di connessione da " + client.getInetAddress());
(new Mserver(client)).start();
}
}
catch(IOException e) {
e.printStackTrace();
}
}
}
Si tratta di un demone in ascolto su una determinata porta, che accetta connessioni in multithread, io credo che il codice sia giusto l ho guardato 1000 volte :(
Provato con altre porte diverse da 900 ma mi da lo stesso risultato, sia con windows che con Linux :(

Lakaj
09-02-2007, 17:41
Sono stato 3 ore a cercare un problema che non c'era...
Non vedevo il messaggio di lancio del server perchè la setVisible del JFrame era impostata esternamente, grazie a quel demente del mio prof che mi ha insegnato cosi'
Ovviamente alla seconda esecuzione del server mi diceva che la porta era già in uso...

-_-'

andbin
09-02-2007, 18:16
Se mi permetti di dirlo, il tuo non è un buon "design". Già solo la classe Interf1 non va affatto bene. Hai usato metodi che agiscono sulla interfaccia utente e metodi che lavorano con i socket allegramente insieme e per di più nel costruttore della classe ... il tutto eseguito dallo stesso thread.

Quando viene costruita l'istanza di Interf1, non sei nel thread di Swing, quindi non dovresti interagire con l'interfaccia utente. Idem nella classe Mserver.

Lakaj
09-02-2007, 19:59
Se mi permetti di dirlo, il tuo non è un buon "design". Già solo la classe Interf1 non va affatto bene. Hai usato metodi che agiscono sulla interfaccia utente e metodi che lavorano con i socket allegramente insieme e per di più nel costruttore della classe ... il tutto eseguito dallo stesso thread.

Quando viene costruita l'istanza di Interf1, non sei nel thread di Swing, quindi non dovresti interagire con l'interfaccia utente. Idem nella classe Mserver.
Aspetta, che intendi per thread di swing ?
Io estendo JFrame appositamente per interagire con Swing...
Intendi che dovrei avere una classe che gestisca separatamente i socket e istanziarla dentro quelle che mi servono ?
Lo dici per un motivo squisitamente estetico oppure pensi che puo' portare a problemi di sincronizzazione coi thread ?

fino a estendere la classe JFrame e implementare la Runnable contemporaneamente mi pare che non ci siano problemi vero ?
Le amenità iniziano utilizzando socket liberi dentro la suddetta e li hai ragionissima...

dimmi la tua...

vabbè si e poi in effetti tutto il codice messo dentro il costruttore è una blasfemia (lo so)

andbin
09-02-2007, 22:46
Aspetta, che intendi per thread di swing ?
Io estendo JFrame appositamente per interagire con Swing...No ... Swing usa un suo apposito thread, al cui interno effettua tutte le operazioni necessarie per gestire/visualizzare/aggiornare l'interfaccia utente ed anche (molto importante!) per dispacciare gli eventi ai vari listener.
Se devi interagire con l'interfaccia utente Swing (es. fare un setText su un componente o cose del genere), devi farlo nel contesto del suo thread, cioè devi essere all'interno di quello che si chiama event-dispatch thread.
Agire sull'interfaccia utente direttamente da un altro thread potrebbe causare problemi di concorrenza!

Leggi <qui> (http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html).

Lakaj
09-02-2007, 23:10
No ... Swing usa un suo apposito thread, al cui interno effettua tutte le operazioni necessarie per gestire/visualizzare/aggiornare l'interfaccia utente ed anche (molto importante!) per dispacciare gli eventi ai vari listener.
Se devi interagire con l'interfaccia utente Swing (es. fare un setText su un componente o cose del genere), devi farlo nel contesto del suo thread, cioè devi essere all'interno di quello che si chiama event-dispatch thread.
Agire sull'interfaccia utente direttamente da un altro thread potrebbe causare problemi di concorrenza!

Leggi <qui> (http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html).
Ah, ma intendi:
// Execute all GUI code on the event dispatch thread, even initialization:
EventQueue.invokeLater(new Runnable() { public void run() {

// Create frame with title "Hello, World!"
JFrame f = new JFrame("Hello, World!");
etc.
etc.

Ah, allora sbaglio totalmente programmazione... :(
Eppure sul Mokabook :ave: ha quella filosofia

Io purtroppo sono vittima della mia università, della mia città e della mia regione, che è forse troppo vicina all'Africa...

Lakaj
10-02-2007, 10:06
Quindi, in teoria, un codice del genere, anche se ordinato e preciso, potrebbe portare a problemi di concorrenza ?

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class JTextFieldExample extends JFrame {
private JTextField textField;
private JLabel label;
public JTextFieldExample() {
super(“JTextField”);
setSize(200, 80);
getContentPane().setLayout(new BorderLayout());
textField = new JTextField();
label = new JLabel();
getContentPane().add(BorderLayout.NORTH, textField);
textField.addActionListener(new EnterTextListener());
getContentPane().add(BorderLayout.SOUTH, label);
setVisible(true);
}
class EnterTextListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
label.setText(“Testo inserito: “ + textField.getText());
textField.setText(“”);
}
}
public static void main(String argv[]) {
JTextFieldExample jtf = new JTextFieldExample();
}
}
:confused:

Lakaj
10-02-2007, 11:42
O meglio, per evitare problemi di concorrenza, dovrei creare un'istanza di JTextFieldExample all'interno di

java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new JTextFieldExample().setVisible(true);
}
});

Dico giusto ?
A quanto ho capito la invokeLater rappresenta un ambiente sicuro in cui esiste certezza che un dato componente A non possa essere disturbato diciamo 'simultaneamente'(anche se in un contesto mono-processore la parola simult. è errata) da 2 diversi blocchi di codice...

andbin
10-02-2007, 15:41
Quindi, in teoria, un codice del genere, anche se ordinato e preciso, potrebbe portare a problemi di concorrenza ?
[...]
Se hai letto bene la pagina che ho linkato, hai sicuramente visto che ci sono delle eccezioni. Nel semplice codice che hai postato, il setVisible(true) lo fai alla fine del costruttore e dopo non fai più nulla con la GUI.
Prima di quella chiamata, il frame non è ancora visibile e non è cioè "realized". Quindi, sebbene tutta la inizializzazione la fai nel contesto del "main" thread e non nel event-dispatch thread, non dovrebbero esserci problemi di concorrenza. Per questo caso specifico, si intende.

O meglio, per evitare problemi di concorrenza, dovrei creare un'istanza di JTextFieldExample all'interno di
[....]
Dico giusto ?Sì, parlando in generale, sarebbe meglio.

A quanto ho capito la invokeLater rappresenta un ambiente sicuro in cui esiste certezza che un dato componente A non possa essere disturbato diciamo 'simultaneamente'(anche se in un contesto mono-processore la parola simult. è errata) da 2 diversi blocchi di codice...invokeAndWait/invokeLater servono solo per chiedere che un Runnable (il metodo run() ) venga eseguito nel contesto del event-dispatch thread.
Quindi, dentro quel Runnable, le operazioni che fai sull'interfaccia utente sono intrinsecamente sicure. Dopotutto il e.d.t. fa solo una cosa per volta ... o sta aggiornando l'interfaccia utente, o sta dispacciando un evento o sta eseguendo un tuo Runnable.

La differenza tra i due metodi è solo il fatto del sincrono/asincrono. E per invokeAndWait c'è da notare che non deve essere usato se si è già nel e.d.t. (altrimenti blocchi tutto!).