2012-04-15 22 views
5

Câu hỏi của tôi nằm trên các giả định sau mà tôi hy vọng là đúng, bởi vì tôi tin rằng những khi tôi đọc chúng trong khi Googling vấn đề của tôi:Làm thế nào bạn có thể buộc một tuôn ra trên một đối tượng OutputStream mà không đóng nó?

  1. Đóng OutputStream của socket đóng phương pháp quá
  2. Các flush() ổ cắm của OutputStream không làm gì cả

Vì vậy, về cơ bản, tôi cần xóa dữ liệu ra khỏi đối tượng OutputStream để ứng dụng của tôi hoạt động.

Nếu bạn quan tâm đến chi tiết, vui lòng xem hai liên kết sau:

. Weird behavior : sending image from Android phone to Java server (code working)

Sự cố này đã được giải quyết bằng cách đóng OutputStream. Làm như vậy xóa tất cả dữ liệu đến đầu kia của ổ cắm và làm cho ứng dụng của tôi làm việc thêm nhưng sửa chữa này nhanh chóng làm phát sinh vấn đề số 2 - ổ cắm tương ứng cũng bị đóng:

. SocketException - 'Socket is closed' even when isConnected() returns true

+2

Nếu – GrowinMan

Trả lời

1

Đóng OutputStream của socket đóng socket quá

True.

Phương pháp tuôn ra() của OutputStream làm gì

False. Có ghi đè. Xem Javadoc cho FilterOutputStream.flush(), BufferedOutputStream.flush(), ObjectOutputStream.flush(), để đặt tên cho một vài.

Vì vậy, vấn đề ban đầu của bạn là không tồn tại, vì vậy bạn không cần phải có 'giải pháp' gây ra vấn đề # 2.

+0

Nhưng sau đó bạn đề xuất gì cho vấn đề # 1. Ban đầu tôi đã sử dụng flush() thay vì close() trên OutputStream nhưng hình ảnh sẽ không được chuyển sau đó .. – GrowinMan

+0

Giải pháp cho vấn đề # 1 không phải là đóng luồng Nếu người ngang hàng cần kết thúc luồng để biết thời điểm tin nhắn hoàn tất, bạn đang sử dụng giao thức ứng dụng sẽ chỉ cho phép một tin nhắn e, vì vậy bạn cần phải thay đổi nó. Không có thư nào trong TCP, chỉ có luồng byte. Tin nhắn tùy thuộc vào bạn. – EJP

+0

tuôn ra không làm gì cả - downvote thấy câu trả lời của tôi – ceph3us

6

Bạn có thể gọi phương thức xả của OutputStream thay vì đóng. Các lớp cụ thể kế thừa từ OutputStream sẽ ghi đè lên flush() để làm điều gì khác hơn là không có gì (ghi dữ liệu vào một tệp hoặc gửi nó qua mạng).

+0

Nhưng nếu bạn thấy câu hỏi đầu tiên tôi đăng, hình ảnh được chuyển qua ổ cắm sẽ không được chuyển cho đến khi OutputStream bị đóng. Và bằng cách sử dụng tuôn ra() không giúp đỡ ở đó. Bạn đề nghị gì ở đó? – GrowinMan

+3

Trong liên kết bạn đã đăng máy chủ đang đợi EOF (cuối tệp) trên luồng. Một EOF được báo hiệu bằng cách đóng luồng và kết nối TCP - vì vậy máy chủ đang chạy trong vòng lặp cho đến khi bạn đóng luồng đầu ra ở phía máy khách. Nếu bạn không muốn đóng luồng sau khi chuyển hình ảnh, bạn phải đưa ra một phương thức khác để báo hiệu khi quá trình truyền ảnh hoàn tất. Cách đơn giản nhất để làm điều đó là gửi kích thước hình ảnh dưới dạng số nguyên (4 byte) trước khi gửi hình ảnh. Sau đó, máy chủ có thể đọc đến số byte đó trước khi thoát khỏi vòng lặp. – smichak

2

Phương thức flush() của OutputStream không làm gì cả.

Điều này không đúng.

Đúng là việc triển khai cơ sở là flush() do lớp OutputStream cung cấp không làm gì cả. Tuy nhiên, ứng dụng của bạn sẽ gọi phiên bản của phương thức đó được cung cấp bởi lớp thực tế luồng mà bạn đang sử dụng. Nếu lớp luồng không có ngữ nghĩa viết trực tiếp, nó sẽ ghi đè flush() để làm những gì được yêu cầu.

Tóm lại, nếu cần xả (và cần thiết cho luồng đầu ra Ổ cắm), sau đó gọi flush() sẽ làm điều đúng. (Nếu một số nguồn internet cho bạn biết nếu không nó là sai hoặc bạn đang hiểu sai nó.)


FYI, lý do mà các dụng cụ cơ sở OutputStreamflush() như một không-op là:

  • một số lượng các lớp suối không cần phải làm bất cứ điều gì khi đỏ mặt; ví dụ: ByteArrayOutputStream
  • cho các lớp dòng nơi flush() không phải là no-op, không có cách nào để triển khai hoạt động ở cấp cơ sở.

Họ có thể (theo lý thuyết) đã thiết kế API luồng sao cho OutputStream là lớp trừu tượng (và flush() phương thức trừu tượng) hoặc giao diện. Tuy nhiên, API này đã bị đóng băng trước Java 1.0 một cách hiệu quả và tại thời điểm đó không có đủ kinh nghiệm với lập trình Java thực tế để nhận ra rằng thiết kế API là tối ưu.

0

Bạn có thực sự cần tuôn ra không? Tôi cũng đã có một vấn đề, nơi mà người nghe trên C# máy chủ không thể nhận được dữ liệu được gửi từ android (Tôi đã cố gắng để có được dữ liệu đồng bộ).

Tôi chắc chắn rằng điều này là do ở bên Android, mã sau không tuôn ra.

OutputStream str = btSocket.getOutputStream(); 
str.write(data_byte); 
// "This implementation does nothing" 
str.flush(); 

Nó bật ra, nếu tôi sử dụng truy xuất dữ liệu không đồng bộ trên trình nghe của máy chủ - nó nhận dữ liệu và không có() phía khách hàng là bắt buộc!

0

Tôi sẽ đâm vào nó. Tôi đã có cùng một vấn đề. đóng outputstream là cách duy nhất tôi có thể "tuôn ra" dữ liệu. nhưng kể từ khi tôi vẫn cần outputstream đó không phải là một lựa chọn. Vì vậy, 1st i gửi chiều dài mảng byte, out.writeInt, sau đó là mảng chính nó. khi tất cả các byte đã được đọc tức là buffer.length == in.readInt() i ngắt vòng

ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream(); 
    byte[] buffer = new byte[1024]; 
    byte[] fileBytes; 
    int n; 
    int length; 

    try 
    { 
     size = in.readInt(); 

     while((n = in.read(buffer)) != -1) 
     { 
      dataBuffer.write(buffer, 0, n); 

      if(dataBuffer.toByteArray().length == length) 
      { 
       fileBytes = dataBuffer.toByteArray(); break; 
      } 
     } 
    } 
0

Tôi đã có cùng một vấn đề. Thêm "\ n" ở cuối luồng. tác phẩm tuôn ra nhưng destinary không biết nếu thông điệp kết thúc

0

YES trên tuôn Android() không làm gì cả (ví dụ dựa trên api 23)

public Socket() { 
    this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl(); 
    this.proxy = null; 
} 

public class PlainSocketImpl extends SocketImpl { 

    @Override protected synchronized OutputStream getOutputStream() throws IOException { 
     checkNotClosed(); 
     return new PlainSocketOutputStream(this); 
    } 


} 

private static class PlainSocketOutputStream extends OutputStream { 
     // doesn't override base class flush(); 
} 

để tuôn dòng đầu ra mà không đóng ổ cắm, bạn có thể tắt máy đầu ra:

protected void shutdownOutput() throws IOException 

- điều này sẽ đóng bộ mô tả tập tin VIẾT.

thay vì sử dụng dòng đầu ra bạn có thể viết trực tiếp vào tập tin mô tả hoặc bằng cách tạo thực hiện Ổ cắm riêng với OutputStream mà sẽ ghi đè phương pháp tuôn ra (ví dụ sử dụng một thực hiện Berkeley socket trong c (thông qua cuộc gọi mẹ đẻ).

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