2017-01-09 8 views
0

ソケット接続を受け入れ、通常のマルチスレッドサーバと同様に、スレッドを解決するJavaサーバ(Java 1.6)があります。しかし、私は同時に接続することはできません。私は、常にメッセージを送受信するクライアントを接続し、2番目のメッセージを接続しようとしますが、2番目のメッセージは、アドレスがすでに使用中であることを示すBindExceptionを返します。概念的にも私のコードでも、マルチスレッドの全体を間違っていますか?サーバへの同時接続はできません。

マイサーバー:

ServerSocket serverSocketUPMS1 = null; 
    try { 
     serverSocketUPMS1 = new ServerSocket(Integer.parseInt(cfg.getProperty("UPMSServerPort"))); 
     serverSocketUPMS1.setSoTimeout(0); 
     log.info("Starting the USSDInterface server at port "+serverSocketUPMS1.getLocalPort()); 
    } catch (IOException e) { 
     log.error("The TCP server couldn't be started",e); 
     finish = true; 
    } 

    while (!finish) { 
      try { 
       log.info("Waiting for a socket to connect..."); 
       Socket subscriberSocket = serverSocketUPMS1.accept(); 
       //Timeout de sesion ussd para poder crear una TimeoutException 
       int timeOutSocket = Integer.parseInt(cfg.getProperty("USSDSocketTimeout")); 
       log.info("New client arrived from " + subscriberSocket.getRemoteSocketAddress()); 

       upms = new USSDSocket2(subscriberSocket,timeOutSocket); 
       Thread t1 = new Thread(upms); 
       t1.setName(Integer.toString(subscriberSocket.getLocalPort()) +","+ subscriberSocket.getRemoteSocketAddress() +", upms"); 
       t1.start(); 
       UPMSSimUtils.createAvailableInstance(upms); 
       log.trace("USSD Socket created and initiated"); 
      } 
      catch (Exception e) { 
       log.warn("There's been an error while working with the server socket"+e.getMessage(), e); 
       try { 
        Thread.sleep(100); 
       } catch (InterruptedException e1) { 
        log.warn("There's been an error while waiting to resume the socket listenting"+e1.getMessage(), e1); 
       } 
      } 
     try { 
      Thread.sleep(100); 
     } catch (InterruptedException e) { 
      log.warn("There's been an error while waiting in the server"+e.getMessage(), e); 
     } 
    } 

    try { 
     serverSocketUPMS1.close(); 
     log.info("TCP Server is now DOWN"); 
    } catch (IOException e) { 
     log.error("There was an error while closing the server socket. TCP Server is now DOWN",e); 
    } 
    upms.stop(); 

処理スレッド:

public void run() { 
    new Thread(new Sender()).start(); 
    while (!finish) { 
     byte buffer[] = new byte[10000]; 
     byte size[] = new byte[4]; 
     try { 
      this.socket.getInputStream().read(size, 0, 4); 
      Integer largo = calcularTamanio(size); 
      log.debug("Size in bytes: "+size); 
      log.debug("Length of the incoming string: " + largo); 
      this.socket.getInputStream().read(buffer, 0, largo); 
      log.debug("Buffer of the incoming string: " + tostr2(buffer)); 
      decodeMessage(parseXML(toStr(buffer)), toStr(buffer)); 

     } catch (SocketException e) { 
      log.error("Socket exception: " + e.getMessage(), e); 
      this.finish = true; 
     } catch (IOException e) { 
      log.error("IO exception: " + e.getMessage(), e); 
      this.finish = true; 
     } catch (JDOMException e) { 
      log.error("JDOM exception: " + e.getMessage(), e); 
     } catch (Exception e) { 
      log.error("Unknown exception: " + e.getMessage(), e); 
      this.finish = true; 
     } 
     // try { 
     // Thread.sleep(1); 
     // } catch (InterruptedException e) { 
     // log.error(e.getMessage(), e); 
     // } 
    } 
    try { 
     this.socket.close(); 
     this.socketUDP.close(); 
    } catch (IOException e) { 
     log.error("Error closing the sockets at the USSDSocket", e); 
    } 
} 

クライアントソケットの作成:

try{ 
       socketsCreated++; 
       log.info("Attempting to create a socket"); 
       Properties properties=Config.getInstance().getCfg(); 

       ussdIface = new USSDInterfaceServerClass(properties); 

       int port=Integer.parseInt(properties.getProperty("TestClientSocketTargetPort")); 

       log.info("Client will connect to "+properties.getProperty("TestClientSocketTargetAddress")+":"+port); 

       clientSocket = new Socket(properties.getProperty("TestClientSocketTargetAddress"),port); 
       log.info("Socket connected"); 
       log.info("Client socket targeting "+properties.getProperty("TestClientSocketTargetAddress")+":"+port+" created"); 

       USSDSocket2 ussdSocket=new USSDSocket2(clientSocket,Integer.parseInt(properties.getProperty("USSDSocketTimeout"))); 
       UPMSSimUtils.createAvailableInstance(ussdSocket); 

       upms = UPMSSimUtils.getAvailable(properties); 

       Thread t1 = new Thread(ussdSocket); 
       t1.setName("ussdsocket client test"); 
       t1.start(); 

       log.info("USSDSocket setted on the UPMSSimUtils"); 

       USSDSocketClientThread socketClientThread=instance.new USSDSocketClientThread(upms, "ClientSocketThread-"+socketsCreated); 
       openSockets.add(socketClientThread); 
       new Thread(socketClientThread).start(); 

       Thread.sleep(waitTimeBetweenConnections); 
      }catch(Throwable throwable){ 
       log.warn("Error with a new connection",throwable); 
       socketsCreated--; 
      } 

のみ機能ソケットを介してデータを送信します。

public void send(String message) throws IOException { 
    log.info("Trying to send message "+message); 
    if (message != null && !"".equals(message)) { 
     int largo = message.length(); 
     // largo = 800; 
     byte largobytes[] = new byte[4]; 
     largobytes[0] = (byte) (largo % 256); 
     largobytes[1] = (byte) (largo/256); 
     largobytes[2] = (byte) (largo & 0x00FF0000); 
     largobytes[3] = 0; 
     this.socket.getOutputStream().write(largobytes); 
     log.trace("Byte length sent: "+largobytes); 
     this.socket.getOutputStream().write(message.getBytes()); 
     log.info("Message sent successfully"); 
    } 
} 

処理スレッドは、ソケットを経由してくるすべてのものを読み上げる役割を担います。次に、decodeMessageは、処理後に同じソケットを介して送信される応答を作成します。別の実用的なクラスでは、ソケットへの参照とその応答を待って、ソケットを通してメッセージを送ることができます。

入出力ストリームから読み込む方法か、プレーンストリームを使用してソケットをバインドするかブロックするかはわかりませんが、実際にどのようなことがわかりますか?私がやっていることは、それが私にそのような種類のエラーを与えるとき、大丈夫です。

+0

'upms'はグローバル変数ですか?そうだとし、そうであれば2番目の接続が 'upms'を上書きし、両方のクライアントスレッドが同じソケットで動作します。 –

+0

'upms'はグローバル変数ではなく、スレッドが開始される前に設定されているスレッドクラスのパラメータです。申し訳ありませんが、私はそれを明確にすべきでした。私は今すぐ直します。 – KatVolkov

+0

ソースポートが一時的であるため、クライアント接続中にBindExceptionを取得するのは珍しいので、アンバインドする必要があります。接続時に明示的にbind()を呼び出していますか?クライアントコードを投稿できますか?それが例外を投げているなら、それが何をしているのかを見る必要があります。 –

答えて

0

すべてを忘れてしまった。エラーは、元のコードメーカーがハードコーディングされたポートで開始するハードコーディングされたソケットを残していたことです。ソケットが使用されていないので、私はその存在に気付かなかった(私は間違って実際のソケットにつながったエラーのスタックトレースを仮定したが、そうではなかった)

関連する問題