2011-11-05 75 views
4

我正在用java創建一個客戶端 - 服務器應用程序,該應用程序允許使用客戶端擺動應用程序(記事本)連接到服務器的許多人。一旦連接,每個客戶端將不得不請求記事本的控制權,以便他們可以編輯它,然後放棄控制權,並將結果發送到所有其他客戶端的平板電腦上。Java多線程服務器邏輯,同步關鍵字,問題

我遇到的主要問題是多線程服務器邏輯,使用主服務器實例和多個線程,與客戶端每一個處理的通信。

我不確定我選擇的結構是否會工作,或者是否會有參與我缺乏的主題是如何工作的理解有些問題,導致數據損壞或者其他某個線程相關的問題。

無論如何,這是服務器端的代碼,我想知道是否有人能告訴我,如果這個系統將沒有錯誤的工作?當然還有更多的邏輯要添加,比如連接數量上限,鎖的等待列表等,但我主要關注線程之間的通信。

我也想知道如何從線程內訪問服務器實例方法,因爲我不知道。 -note,這已經算出來了,我使用了一個共享的「lock」對象,它有一個線程實例列表,每個線程實例都有鎖定實例,所以他們可以在eachother上調用方法。

非常感謝。

import java.net.*; 
import java.io.*; 
import java.util.ArrayList; 


public class server { 

    private ArrayList<ClientServiceThread> SocketList; 
    private int lock = 0; 
    private ServerSocket myServerSocket; 
    private Socket mySocket; 

    public static void main(String[] args) 
    { 
     server myserver = new server(); 
    } 

    public server() 
    { 

     /** 
     * This will (when finished) accept only a certain number of connections, 
     * and will then finish the constructor by breaking the while loop. It will 
     * then sit here waiting for the synchronised methods to be called by its worker 
     * threads. 
     */ 
     try{ 

      myServerSocket = new ServerSocket(8080); 

     }catch(Exception e) 
     { 
      System.out.println("Could not create serversocket "+e); 
     } 

     int id = 1; 
     while(true) 
     { 
      try{ 

       mySocket = myServerSocket.accept(); 
       ClientServiceThread cliThread = new ClientServiceThread(mySocket, id); 
       SocketList.add(cliThread); 
       id++; 
       cliThread.start(); 

      }catch(Exception e) 
      { 
       System.out.println("Problem with accepting connections"); 
      } 

     } 

    }//end constructor 


    public synchronized boolean acquireLock(int id) 
    { 
     /** 
     * Here any spawned thread can try to acquire the lock, 
     * so it can be the one to send the data (synchronised to prevent data corruption) 
     */ 

     if(this.lock == 0){ 
      this.lock = id; 
      return true; 
     } 
     else 
     { 
      return false; 
     } 

    } 

    public synchronized void releaseLock(int id) 
    { 
     /** 
     * Any thread can call this, releasing the lock. of course, the lock will only be 
     * released if the thread calling it actually owns the lock. 
     */ 

     if(id == this.lock) 
     { 
      this.lock = 0; 
     } 
     else 
     { 
      //do nothing 
     } 
    } 

    public synchronized void publish(String toSend) 
    { 
     /** 
     * When a thread in control of the lock wants to publish to all other threads, it 
     * invokes this method, which then calls another synchronised method on each thread 
     * in the list, telling it to write to it's client with the new data. 
     */ 

     for(int i = 0; i<this.SocketList.size(); i++) 
     { 
      if(i != this.lock) 
      { 
       this.SocketList.get(i).sendData(toSend); 
      } 
     } 
    } 


} 



class ClientServiceThread extends Thread{ 

    Socket mySocket; 
    int id; 
    boolean hasControl = false; 

    public ClientServiceThread(Socket mySocket, int id) 
    { 
     /** 
     * this constructor gives it the ID and the socket for communication, it will 
     * then be run 
     */ 
     this.mySocket = mySocket; 
     this.id = id; 

    } 

    @Override 
    public void run() 
    { 
     //listen, it will be either a request, or some data 
     //based on whether the client is the one in control or not (hasControl) 
     try{ 
      //create buffered reader 

      if(!this.hasControl) 
      { 
       //it has control, so wait for the lines 
      } 
      else 
      { 
       //read in one line and then call acquire lock because we know 
       //that it has sent a request for control 
       // how do i access the original class for acquireLock();? 


      } 


     }catch(IOException e) 
     { 
      System.out.println("Problem reading from the socket"); 
     } 

    } 

    public synchronized void sendData(String toSend) 
    { 
     //create writer and send to my client, saying "true" or some other message 
     //the client will recognise as the go-ahead to edit the data. 
    } 


} 

回答

2

你可能會更好過使用類似MINA而不是滾動您自己。將客戶端命令放入併發隊列中並逐個處理它們,因此您不必擔心同步。

另外,考慮使用RESTful接口而非插槽(或就此而言,東西比一個小程序等,喜歡的Ext JS)。

+0

嗨,感謝您的迴應,我確定這些實現更適合,但我忘了提及這是一個大學項目,必須涉及擺動和套接字不幸:( –

+0

你會想添加「作業「標籤到您的帖子然後... –

+0

噢好吧,我是新來的,有史以來第一個問題:p –