2012-04-25 28 views
7

Làm cách nào để thiết kế vòng lặp đọc và ghi hoạt động trên một ổ cắm đơn (hỗ trợ hoạt động đọc và ghi song song)? Tôi có phải sử dụng nhiều luồng không? Là giải pháp (java) của tôi có tốt không? Còn lệnh ngủ đó thì sao? Làm thế nào để bạn sử dụng nó trong vòng lặp như vậy?Cách thực hành tốt nhất để đọc/ghi vào ổ cắm máy chủ java

Tôi đang cố gắng sử dụng 2 Chủ đề:

đọc

public void run() { 
    InputStream   clientInput; 
    ByteArrayOutputStream byteBuffer; 
    BufferedInputStream bufferedInputStream; 
    byte[]    data; 
    String    dataString; 
    int     lastByte; 

    try { 
     clientInput   = clientSocket.getInputStream(); 
     byteBuffer   = new ByteArrayOutputStream(); 
     bufferedInputStream = new BufferedInputStream(clientInput); 

     while(isRunning) { 

      while ((lastByte = bufferedInputStream.read()) > 0) { 
       byteBuffer.write(lastByte); 
      } 
       data  = byteBuffer.toByteArray(); 
       dataString = new String(data); 
       byteBuffer.reset();  
     } 

    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

Viết

public void run() { 
    OutputStream clientOutput; 
    byte[]  data; 
    String  dataString; 

    try { 
     clientOutput = clientSocket.getOutputStream(); 

     while(isOpen) { 

      if(!commandQueue.isEmpty()) { 
       dataString = commandQueue.poll(); 
       data  = dataString.getBytes(); 
       clientOutput.write(data); 
      }     
      Thread.sleep(1000); 
     }  
     clientOutput.close();   
    } 
    catch (IOException e) { 
     e.printStackTrace(); 
    } 
    catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

đọc thất bại trong việc đưa ra một kết quả hợp lý, vì không có -1 gửi. Làm cách nào để giải quyết vấn đề này?

Vòng ngủ/ghi này có phải là giải pháp tốt không?

+1

Đây có phải là Java không? Vui lòng gắn thẻ ngôn ngữ –

+0

đây là java, nhưng đây là một câu hỏi thiết kế và không liên quan đến bất kỳ tính năng java nào – Schifty

+2

Đúng, nhưng nó làm cho câu hỏi cụ thể hơn –

Trả lời

4

Về cơ bản có ba cách để làm mạng I/O:

  1. Chặn. Trong chế độ này, việc đọc và ghi sẽ chặn cho đến khi chúng có thể được thực hiện, vì vậy nếu bạn muốn làm cả hai cùng lúc, bạn cần các luồng riêng biệt cho mỗi.

  2. Không chặn. Trong chế độ này đọc và ghi sẽ trả về số không (Java) hoặc bằng một số ngôn ngữ (C) chỉ báo trạng thái (return == -1, errno = EAGAIN/EWOULDBLOCK) khi chúng không thể hoàn thành, vì vậy bạn không cần các luồng riêng biệt, nhưng bạn cần API thứ ba cho bạn biết khi nào các hoạt động có thể đáp ứng được. Đây là mục đích của API select().

  3. I/O không đồng bộ, trong đó bạn lên lịch chuyển và được trả lại một số loại xử lý qua đó bạn có thể thẩm tra trạng thái chuyển hoặc trong các API nâng cao hơn, gọi lại.

Bạn nên chắc chắn không bao giờ sử dụng while (in.available() > 0)/sleep() phong cách bạn đang sử dụng ở đây. InputStream.available() có ít sử dụng đúng và đây không phải là một trong số chúng, và giấc ngủ theo nghĩa đen là một sự lãng phí thời gian. Các dữ liệu có thể đến trong thời gian ngủ, và một bình thường read() sẽ thức dậy ngay lập tức.

+0

Bạn có muốn so sánh giải pháp thứ nhất và thứ hai của mình không - cách bạn chọn phương pháp tiếp cận của mình? ví dụ của tôi trông giống như cách tiếp cận thứ 2 của bạn - bạn đánh giá giải pháp của mình như thế nào? – Schifty

+0

@Schifty Nó đi xuống đến bao nhiêu kết nối bạn cần để xử lý cùng một lúc.Hàm 'select()' được phát triển trước các luồng, khi một kết nối khác có nghĩa là một tiến trình khác thay thế. Các luồng là các tiến trình nhẹ, vì vậy có một đối số cho biết bạn không bao giờ cần phải sử dụng 'select()' trong tất cả những ngày này, và một đối số khác nói rằng sử dụng 'select()' có nghĩa là bạn đang chuyển đổi đầu vào các vòng lặp trong quá trình. Tại thời điểm này trong lịch sử, tôi sẽ sử dụng các chuỗi tối đa 10.000 kết nối, có thể là 100.000, tùy thuộc vào nền tảng. – EJP

0

Bạn nên sử dụng biến boolean thay vì trong khi (đúng) để đóng đúng chuỗi khi bạn muốn. Cũng có, bạn nên tạo nhiều luồng, mỗi luồng cho mỗi khách hàng được kết nối, vì luồng sẽ tự chặn cho đến khi một dữ liệu mới được nhận (với DataInputStream(). Read() chẳng hạn). Và không, đây không phải là câu hỏi thiết kế, mỗi thư viện/khung hoặc ngôn ngữ có cách riêng để nghe từ ổ cắm, ví dụ để nghe từ ổ cắm trong Qt bạn nên sử dụng cái gọi là "tín hiệu và khe", chứ không phải vòng lặp vô hạn.

+0

DataInputStream(). Read() không chặn vì. > 0 – Schifty

+0

@Schifty Nhưng bạn không gọi có sẵn(), và bạn không nên. – EJP

Các vấn đề liên quan