2015-01-06 2 views
1

У меня есть сервер, который на клиентах посылает для отправки пакета через DatagramSocket. Но когда в клиенте я использовать те же порты, как сервер (так что они могут общаются) я получаю исключение в стороне клиента:DatagramSocket в клиенте, не привязанный к порту на сервере. Порт уже используется

Exception in thread "main" java.net.BindException: Address already in use: Cannot bind 
at java.net.DualStackPlainDatagramSocketImpl.socketBind(Native Method) 
at java.net.DualStackPlainDatagramSocketImpl.bind0(DualStackPlainDatagramSocketImpl.java:80) 
at java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:93) 
at java.net.DatagramSocket.bind(DatagramSocket.java:372) 
at java.net.DatagramSocket.<init>(DatagramSocket.java:222) 
at java.net.DatagramSocket.<init>(DatagramSocket.java:279) 
at tp.Repositorio.main(Cliente.java:146) 

Так на стороне сервера у меня есть поток, который Wating на пакеты. Что-то вроде этого:

addr = InetAddress.getByName("localhost"); 
DatagramSocket socket = new DatagramSocket(5008, addr); 
DatagramPacket packet = new DatagramPacket(buff, buff.length); 
while(true) 
    { 
     s.receive(packet); 
// and then it throws another thread to treat the packet... 
    } 

А на стороне клиента, у меня есть что-то вроде этого:

InetAddress inet; 
inet = InetAddress.getByName("localhost"); 
s_data = new DatagramSocket(5008, inet); 

Я пытался изменить порт в обе стороны, но он также дал мне это исключение. Если я изменю порты, например, 5003 на сервере и 5004 в Клиенте, это не дает мне никаких исключений (конечно), но они не могут соединяться между собой.

У вас есть идеи, чтобы решить эту проблему?

Спасибо.

Edit:

Вот следующий код клиента (он называется repositorio):

/* 
* To change this license header, choose License Headers in Project Properties. 
* To change this template file, choose Tools | Templates 
* and open the template in the editor. 
*/ 
package tp; 

import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.IOException; 
import java.io.ObjectOutput; 
import java.io.ObjectOutputStream; 
import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.Inet4Address; 
import java.net.InetAddress; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.ArrayList; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

/** 
* 
* @author Diogo 
*/ 
public class Repositorio { 
    static int nr_ligacoes; 
    static int porto; 
    static String endereco; 


    Repositorio(int pt, String end) 
    { 
     this.porto = pt; 
     this.endereco = end; 
    } 

    public static void setNr_ligacoes(int nr_ligacoes) { 
     Repositorio.nr_ligacoes = nr_ligacoes; 
    } 

    public static void setPorto(int porto) { 
     Repositorio.porto = porto; 
    } 

    public static void setEndereco(String endereco) { 
     Repositorio.endereco = endereco; 
    } 



    public File[] getFicheiros() 
    { 
     File folder = new File("C:\\temp2"); 

     File[] ficheiros = folder.listFiles(); 


     for (int i = 0; i < ficheiros.length; i++) { 
      if (ficheiros[i].isFile()) { 
       System.out.println("File " + ficheiros[i].getName()); 
      } else if (ficheiros[i].isDirectory()) { 
       System.out.println("Directory " + ficheiros[i].getName()); 
      } 
     } 

     return ficheiros; 
    } 

    public int getNr_ligacoes() { 
     return nr_ligacoes; 
    } 


    public int getPorto() { 
     return porto; 
    } 

    public String getEndereco() { 
     return endereco; 
    } 

    public ArrayList<String> getListadeFicheiros() 
    { 
     ArrayList<String> fich_nome = new ArrayList<>(); 
     File[] fich = getFicheiros(); 

     for(int i = 0; i <fich.length ; i++) 
      fich_nome.add(fich[i].getName()); 

     return fich_nome; 
    } 

    public boolean VerFicheiro(String nome) 
    { 
     File[] fich = getFicheiros(); 


     for(int i = 0; i<fich.length;i++) 
      if(nome.compareTo(fich[i].getName()) == 0) 
       return true; 
     return false; 
    } 




    public static void main(String[] args) throws IOException 
    { 
     ServerSocket socket_r; 
     File localDirectory; 
     DatagramSocket s_data; 
     DatagramPacket p; 


     /* if(args.length != 4){ 
     System.out.println("Sintaxe: java Repositorio serverTcpPort serverAddress localDirectory"); 
     return; 
     } */ 

     localDirectory = new File("C:\\temp2"); 

     if(!localDirectory.exists()){ 
      System.out.println("A directoria " + localDirectory + " nao existe!"); 
      return; 
     } 

     if(!localDirectory.isDirectory()){ 
      System.out.println("O caminho " + localDirectory + " nao se refere a uma directoria!"); 
      return; 
     } 

     if(!localDirectory.canWrite()){ 
      System.out.println("Sem permissoes de escrita na directoria " + localDirectory); 
      return; 
     } 

     //Repositorio r = new Repositorio(5002,"localhost"); 
     InetAddress inet; 
     inet = InetAddress.getByName("localhost"); 
     socket_r = new ServerSocket(5003); 

     new lancaRepositorioCliente(socket_r, localDirectory).start(); 

     s_data = new DatagramSocket(5008, inet); 

     new lancarepositorioServidor(s_data, localDirectory).start(); 


    } 




    static class lancarepositorioServidor extends Thread{ 

     DatagramSocket s; 
     File localDirectory; 
     ListadeRepositorios listaRep; 

     lancarepositorioServidor(DatagramSocket s_data, File local) 
     { 
      this.localDirectory = local; 
      this.s = s_data; 
     } 

     @Override 
     public void run() { 
      System.out.println("Estou no lanca to servidor"); 
      byte[] buf = new byte[10000]; 
      DatagramPacket pack = new DatagramPacket(buf, 128); 

      new repositorioToServidor(pack,s).start(); 

     } 

    } 
    static class repositorioToServidor extends Thread{ 
     DatagramPacket pack; 
     DatagramSocket s; 

     public repositorioToServidor(DatagramPacket packet, DatagramSocket s) { 
      this.pack = packet; 
      this.s = s; 

     } 

     @Override 
     public void run() { 

      while(true) 
      { 
       try { 
        sleep(10000); 
       } catch (InterruptedException ex) { 
        Logger.getLogger(Repositorio.class.getName()).log(Level.SEVERE, null, ex); 
       } 
       ByteArrayOutputStream bos = new ByteArrayOutputStream(2048); 
       ObjectOutputStream oos; 
       try { 
        oos = new ObjectOutputStream(bos); 
        oos.writeObject(new Notificacao(nr_ligacoes)); 

        DatagramPacket packet = new DatagramPacket(bos.toByteArray(), bos.size()); 
        s.send(packet); 

       } catch (IOException ex) { 
        Logger.getLogger(Repositorio.class.getName()).log(Level.SEVERE, null, ex); 
       } 


      } 


     } 


    } 


    static class repositorioToCliente extends Thread{ 
     Socket s; 
     File localDirectory; 

     public repositorioToCliente(Socket s, File local) { 
      this.s = s; 
      this.localDirectory = local; 
     } 

     public Socket getS() { 
      return s; 
     } 

     @Override 
     public void run() { 

      System.out.println("Estou no lanca to cliente"); 


     } 


    } 


    static class lancaRepositorioCliente extends Thread{ 
     ServerSocket s; 
     File localDirectory; 

     public lancaRepositorioCliente(ServerSocket s, File local) { 
      this.s = s; 
      this.localDirectory = local; 
     } 

     public ServerSocket getS() { 
      return s; 
     } 

     @Override 
     public void run() { 
      Socket sClient; 

      while(true) 
      { 
       try { 
        sClient = s.accept(); 

        new repositorioToCliente(sClient,localDirectory).start(); 
        // vamos aqui receber o ficheiro que é para eliminar/depositar 

       } catch (IOException ex) { 
        Logger.getLogger(Repositorio.class.getName()).log(Level.SEVERE, null, ex); 
       } 
      } 

     } 


    } 

} 

код сервера:

package tp; 

/* 
* To change this license header, choose License Headers in Project Properties. 
* To change this template file, choose Tools | Templates 
* and open the template in the editor. 
*/ 

import java.io.BufferedReader; 
import java.io.ByteArrayInputStream; 
import java.io.File; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.PrintWriter; 
import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.InetAddress; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.nio.charset.Charset; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.Paths; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.logging.Level; 
import java.util.logging.Logger; 


/** 
* 
* @author Diogo 
*/ 
public class Servidor{ 

    protected File localDirectory; 
    static String LoginfileName; 
    //List <Repositorio> rep = null; 
    static ListadeRepositorios listaRep; 
    static ArrayList <String> ficheiros = null; 

    public Servidor() 
    { 
     this.ficheiros = new ArrayList<>(); 
    } 

    public void setFicheiros(List <String> a) 
    { 
     a.stream().forEach((a1) -> { 
      ficheiros.add(a1); 
     }); 
    } 

    public static void main(String[] args) throws IOException 
    { 
     Servidor s = new Servidor(); 
     ListadeRepositorios lista_rep = new ListadeRepositorios(); 
     int listeningPort1; 
     int listeningPort2; 
     ServerSocket serverSocket; 
     InetAddress addr; 
     DatagramSocket socket; 

     try { 

      //listeningPort = Integer.parseInt(args[0]); 
      listeningPort1 = 5001; 
      listeningPort2 = 5008; 

      if(listeningPort1 <= 0) throw new NumberFormatException("Porto TCP de escuta indicado <= 0 (" + listeningPort1 + ")"); 


      LoginfileName = "c:/temp/users.txt"; 

      serverSocket = new ServerSocket(listeningPort1); 

      serverSocket.setSoTimeout(1000000000); 

      new lancaCliente(serverSocket, LoginfileName).start(); 

      addr = InetAddress.getByName("localhost"); 
      socket = new DatagramSocket(listeningPort2, addr); 


      new lancaRepositorio(socket).start(); 


     }catch(NumberFormatException e){ 
      System.out.println("O porto de escuta deve ser um inteiro positivo."); 
     } 
    } 


    static class lancaCliente extends Thread{ 

     ServerSocket s; 
     String Login; 

     public lancaCliente(ServerSocket s, String Login) { 

      this.s = s; 
      this.Login = Login; 
     } 

     @Override 
     public void run() { 
      Socket accept; 

      while(true) 
      { 
       try { 

        System.out.println("Servidor à espera de clientes: "); 


        accept = s.accept(); 
        System.out.println("Servidor aceitou Cliente"); 

        new atendeCliente(accept, this.Login).start(); 


       } catch (IOException ex) { 
        Logger.getLogger(lancaCliente.class.getName()).log(Level.SEVERE, null, ex); 
       } 


      } 

     } 

    } 

    static class atendeCliente extends Thread{ 

     int porto; 
     //List<Repositorio> repositorios; 
     List<String> clienteLogado; 
     //List<Socket> socketsAbertos; 
     List<String> infoFicheiros; 
     Socket Scliente; 
     List<String> lines; 
     String arg0 = null,arg1 = null, arg2=null; 
     String[] comando; 
     String filename; 
     ListadeRepositorios listaRep2; 


     public static final int TIMEOUT = 5; //segundos 

     atendeCliente(Socket s, String nome) 
     { 
      this.Scliente = s; 
      this.filename = nome; 
     } 



     protected int processaLogin(String user, String pass) throws IOException 
     { 
      String separaUser = null, separaPass=null; 
      String[] separa; 

      Path caminho = Paths.get("C:/temp/users.txt"); 

      Charset charset = Charset.forName("ISO-8859-1"); 

      try { 
       lines = Files.readAllLines(caminho, charset); 

       lines.stream().forEach((line) -> { 
        System.out.println(line); 
       }); 
      } catch (IOException e) { 
       System.out.println(e); 
      } 

      for(int i = 0; i<lines.size();i++) 
      { 
       separa = lines.get(i).split("\\s+"); 
       separaUser = separa[0]; 
       separaPass = separa[1]; 

       if(user.compareTo(separaUser) == 0 && pass.compareTo(separaPass)==0) 
        return 1; 
      } 
      return 0; 

     } 


     @Override 
     public void run() 
     { 
      BufferedReader buf = null; 
      PrintWriter escreve = null; 
      int estaLogado; 
      String mensagem = ""; 

      try { 
       buf = new BufferedReader(new InputStreamReader(Scliente.getInputStream())); 
      } catch (IOException ex) { 
       Logger.getLogger(atendeCliente.class.getName()).log(Level.SEVERE, null, ex); 
      } 
      try { 
       escreve = new PrintWriter(Scliente.getOutputStream()); 
      } catch (IOException ex) { 
       Logger.getLogger(atendeCliente.class.getName()).log(Level.SEVERE, null, ex); 
      } 

      try { 
       while(true) 
       { 
        try { 
         buf = new BufferedReader(new InputStreamReader(Scliente.getInputStream())); 
        } catch (IOException ex) { 
         Logger.getLogger(atendeCliente.class.getName()).log(Level.SEVERE, null, ex); 
        } 

        System.out.println("Estou a espera de uma mensagem do cliente"); 
        mensagem = buf.readLine(); 

        System.out.println("Recebi: " + mensagem); 
        comando = mensagem.split("\\s+"); 
        arg0 = comando[0]; 
        arg1 = comando[1]; 
        arg2 = comando[2]; 
        System.out.println(comando[0] + comando[1] + comando[2]); 
        System.out.println(arg0 + arg1 + arg2); 
        if("login".compareTo(arg0)==0) 
        { 
         estaLogado = processaLogin(arg1, arg2); 
         if (estaLogado == 0) 
         { 
          escreve.println("Nao existe!"); 
          escreve.flush(); 
         } 
         else 
         { 
          escreve.println("LoginFeito"); 
          escreve.flush(); 
         } 
        } 

        else if("deposita".compareTo(arg0)==0 || "apaga".compareTo(arg0) == 0) 
        { 
         Repositorio rep; 
         rep = listaRep2.MenosCongest(); 
         int porto_rep = rep.getPorto(); 
         String end_rep = rep.getEndereco(); 
         String porto_s = Integer.toString(porto_rep); 
         String comandoToCliente = end_rep + " " + porto_s; 

         escreve.println(comandoToCliente); 
         escreve.flush(); 
        } 

        else if("listaficheiros".compareTo(arg0) == 0) 
        { 
         ObjectOutputStream outB = new ObjectOutputStream(Scliente.getOutputStream()); 
         ficheiros.add("f1.txt"); 
         ficheiros.add("f2.txt"); 
         ficheiros.add("f3.txt"); 
         ficheiros.add("f4.txt"); 

         //ficheiros_disponiveis = listaRep.getFicheiros(); 

         outB.writeObject(ficheiros); 
         outB.flush(); 
        } 

        mensagem = ""; 
       } 



      } catch (IOException ex) { 
       Logger.getLogger(atendeCliente.class.getName()).log(Level.SEVERE, null, ex); 
      }catch (Exception e){ 
      } 

     } 

    } 


    static class lancaRepositorio extends Thread{ 

     DatagramSocket ser; 
     ListadeRepositorios listaRep; 

     public lancaRepositorio(DatagramSocket s) 
     { 
      this.ser = s; 
     } 


     @Override 
     public void run() { 

      byte[] buff = new byte[1024]; 

      DatagramSocket s = this.ser; 
      DatagramPacket packet = new DatagramPacket(buff, buff.length); 
      Repositorio r; 

      while(true) 
      { 
       try { 
        System.out.println("Sevidor à espera de repositorios:"); 
        s.receive(packet); 
        System.out.println("Sevidor recepbeu repositorios"); 
        r = new Repositorio(packet.getPort(),packet.getAddress().getHostAddress()); 

        listaRep.addRepositorio(r); 
        new atendeRepositorio(s,r).start(); 



       } catch (IOException ex) { 
        Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex); 
       } 
      } 

     } 

    } 



    static class atendeRepositorio extends Thread{ 

     DatagramSocket so; 
     Repositorio r; 

     public atendeRepositorio(DatagramSocket s, Repositorio r) 
     { 
      this.so = s; 
      this.r = r; 
     } 

     @Override 
     public void run() { 
      while(true) 
      { 
       try { 
        byte[] incomingData = new byte[1024]; 
        DatagramPacket incomingPacket = new DatagramPacket(incomingData, incomingData.length); 

        so.receive(incomingPacket); 

        byte[] data = incomingPacket.getData(); 

        ByteArrayInputStream in; 
        in = new ByteArrayInputStream(data); 

        try (ObjectInputStream iStream = new ObjectInputStream(new ByteArrayInputStream(data))) { 
         Notificacao n1 = (Notificacao) iStream.readObject(); 

         for(int i = 0;i<listaRep.getListaRepositorios().size();i++) 
         { 
          if(r == listaRep.getListaRepositorios().get(i)) 
          { 
           r.setNr_ligacoes(n1.getN_op()); 
          } 

         } 

        } 


       } catch (IOException ex) { 
        Logger.getLogger(atendeRepositorio.class.getName()).log(Level.SEVERE, null, ex); 
       } catch (ClassNotFoundException ex) { 
        Logger.getLogger(atendeRepositorio.class.getName()).log(Level.SEVERE, null, ex); 
       } 
      } 
     } 



    } 



} 
+0

Да, я. В той же машине. –

+1

Предоставление им того же порта не будет работать. Обычно вам не обязательно указывать номер порта для клиентского сокета (ОС назначит что-то неиспользуемое). Однако при установлении соединения или отправке дейтаграммы UDP вам необходимо указать адрес другого однорангового узла. Здесь вы должны указать тот же номер порта (вместе с адресом сервера). Как вы связываете/отправляете свои сообщения на клиента? – Inspired

+0

Я обновил сообщение, чтобы включить клиент и код сервера. –

ответ

3

Проходя Java Network Programming Book's Chapter 12. UDP, я обнаружил следующее о DatagramSocket: -

Все сокеты дейтаграмм привязываются к локальному порту, на котором они прослушивают входящих данных и которые они размещают в заголовке исходящих дейтаграмм. Если вы пишете клиент, вам все равно, что такое локальный порт , поэтому вы вызываете конструктор, который позволяет системе назначать неиспользуемый порт (анонимный порт). Этот номер порта помещается в любые исходящие граммы и будет использоваться сервером для адресации любых дейтаграмм ответов .

Если вы пишете сервер, клиентам необходимо знать , на каком порту сервер прослушивает входящие графы данных; поэтому, когда сервер создает DatagramSocket, указывает локальный порт , на котором он будет слушать. Тем не менее, сокеты, используемые клиентами и серверами, в остальном идентичны: они отличаются только , независимо от того, используют ли они анонимный (назначенный системой) или известный порт. Не существует различия между клиентскими сокетами и сокетами сервера, так как есть с TCP. Нет такой вещи, как DatagramServerSocket.

РЕШЕНИЕ: -

Вы, вероятно, путают между двумя портами.В DatagramSocket клиента должен использоваться анонимный порт, тогда как пакет, который вы отправляете на сервер, должен быть отправлен на сервер с использованием порта сервера. Оба - разные вещи. Вероятно, это не приведет к генерации BindException.

Просто используйте следующий вызов конструктора в вашем Cliente.java для создания клиентского сокета: -

DatagramSocket socket = new DatagramSocket(); 

И в DatagramPacket, предназначенный для сервера должны использовать один и тот же номер порта, как сервера: -

DatagramPacket packet = new DatagramPacket(buf, buf.length, 
          address, 5008); // server's port number is 5008 
socket.send(packet); 

Я надеюсь, что это поможет решить вашу проблему ...

+0

Ты был абсолютно прав мой друг !! Большое спасибо!! : D –

+0

@AM_I_Полный, откуда вы получите адрес? – YLS

+0

@YLS - Вот почему параметр «адрес» присутствует в конструкторе DatagramPacket. Это InetAddress сервера, на который должен быть отправлен запрос! Обычно вы узнаете адрес сервера перед началом соединения сокета. –

Смежные вопросы