2009-09-20 14 views
11

Đơn giản là tôi đã cố gắng triển khai những gì BufferedStreamReader thực hiện trong Java. Tôi có một dòng ổ cắm mở và chỉ muốn đọc nó trong một dòng thời trang theo định hướng - từng dòng.C# - StreamReader.ReadLine không hoạt động bình thường!

Tôi có mã máy chủ sau.

while (continueProcess) 
     { 
      try 
      { 
       StreamReader reader = new StreamReader(Socket.GetStream(), Encoding.UTF8); 
       string command = reader.ReadLine(); 
       if (command == null) 
        break; 

       OnClientExecute(command); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.ToString()); 
      } 
     } 

Và client-mã sau:

TcpClient tcpClient = new TcpClient(); 
     try 
     { 
      tcpClient.Connect("localhost", serverPort); 
      StreamWriter writer = new StreamWriter(tcpClient.GetStream(), Encoding.UTF8); 
      writer.AutoFlush = true; 
      writer.WriteLine("login>user,pass"); 
      writer.WriteLine("print>param1,param2,param3"); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
     finally 
     { 
      tcpClient.Close(); 
     } 

Các máy chủ chỉ đọc dòng đầu tiên (login>user,pass) và sau đó ReadLine lợi nhuận rỗng!

Cách dễ nhất để đạt được đầu đọc định hướng dòng này vì nó nằm trong số BufferedStreamReader của Java? : s

+1

Vui lòng hủy bỏ các đối tượng của bạn tại đây (StreamReader và StreamWriter). Nếu không, bạn có thể gặp phải các sự cố không mong muốn. Đơn giản chỉ cần đặt một khối sử dụng xung quanh chúng (như trong sử dụng (StreamWriter writer = ...) {}), và bạn sẽ được ok – configurator

+0

Không phải là nó có liên quan đến câu hỏi - chỉ là một gợi ý. – configurator

+0

tuyệt vời;) Nhờ – Aleyna

Trả lời

12

Một dòng-reader điển hình là cái gì đó như:

using(StreamReader reader = new StreamReader(Socket.GetStream(), Encoding.UTF8)) { 
    string line; 
    while((line = reader.ReadLine()) != null) { 
     // do something with line 
    } 
} 

(lưu ý using để đảm bảo chúng tôi Dispose() nó ngay cả khi chúng tôi nhận được một lỗi, và vòng lặp)

Nếu bạn muốn, bạn có thể tóm tắt điều này (tách các mối quan tâm) với một khối lặp:

static IEnumerable<string> ReadLines(Stream source, Encoding encoding) { 
    using(StreamReader reader = new StreamReader(source, encoding)) { 
     string line; 
     while((line = reader.ReadLine()) != null) { 
      yield return line; 
     } 
    } 
} 

(lưu ý chúng tôi đã chuyển tính năng này và xóa "làm điều gì đó", thay thế ng nó với "yield return", mà tạo ra một iterator (một uể oải lặp, không đệm state machine)

Sau đó chúng tôi sẽ tiêu thụ này đơn giản như:

foreach(string line in ReadLines(Socket.GetStream(), Encoding.UTF8)) { 
    // do something with line 
} 

Bây giờ chúng tôi đang xử lý không cần phải lo lắng về việc cách để đọc các dòng - chỉ cần được cung cấp một chuỗi các dòng, làm điều gì đó với chúng.

Lưu ý rằng using (Dispose()) cũng áp dụng cho TcpClient; bạn nên tạo thói quen kiểm tra IDisposable; ví dụ (vẫn bao gồm lỗi đăng nhập của bạn):

using(TcpClient tcpClient = new TcpClient()) { 
    try { 
     tcpClient.Connect("localhost", serverPort); 
     StreamWriter writer = new StreamWriter(tcpClient.GetStream(), Encoding.UTF8); 
     writer.AutoFlush = true; 
     writer.WriteLine("login>user,pass"); 
     writer.WriteLine("print>param1,param2,param3"); 
    } catch (Exception ex) { 
     Console.Error.WriteLine(ex.ToString()); 
    } 
} 
+0

Khi tôi sử dụng StreamReader để đọc từ ổ cắm, tôi thấy rằng chương trình máy khách bị đóng băng, mất một lượng thời gian vô hạn tại phương thức ReadLine() và cuối cùng là không đọc được. –

+0

@MasudRahman thường có nghĩa là: máy chủ không gửi một dòng hoàn chỉnh (nghĩa là bạn đang yêu cầu máy chủ chờ một thứ gì đó mà máy chủ không có lý do để gửi cho bạn) hoặc máy chủ đã quên xóa bộ đệm đầu ra. Bạn * có thể * thêm một thời gian chờ đọc, nhưng cuối cùng nó không thể làm cho máy chủ gửi dữ liệu. Tất nhiên bạn có thể tự đọc và tự đệm, nhưng điều này chỉ làm thay đổi bản chất của vấn đề - sau đó bạn có thể quyết định rằng một dòng hoàn chỉnh chưa được gửi sau một khoảng thời gian nào đó. –

5

Thời gian trong mã máy chủ của bạn được thiết lập để chỉ đọc một dòng cho mỗi kết nối. Bạn sẽ cần một thời gian khác trong khi cố gắng đọc tất cả các dòng đang được gửi. Tôi nghĩ rằng khi luồng đó được thiết lập ở phía máy khách, nó sẽ gửi tất cả dữ liệu. Sau đó, ở phía máy chủ, luồng của bạn chỉ có hiệu quả khi đọc một dòng từ luồng cụ thể đó.

+0

Sau khi thay đổi máy chủ của tôi và mã khách hàng như sau server: sử dụng (StreamReader reader = StreamReader mới (Socket.GetStream(), Encoding.UTF8)) { while (continueProcess) .... khách hàng : ... Thread.Sleep (10000); writer.WriteLine ("print> test, one, two"); Tôi đã chèn Thread.Sleep (10000) vào mã máy khách và máy chủ của tôi bắt đầu ném ngoại lệ. Các ổ cắm khách hàng sẽ được mở cho đến khi khách hàng thoát và vì khách hàng sẽ gửi dữ liệu trong suốt vòng đời của nó có vẻ như mã này sẽ ném lỗi. Bạn không nghĩ vậy sao? – Aleyna

+0

Nếu không thấy mã mới hoặc ngoại lệ mới là gì, tôi không chắc chắn vấn đề có thể là gì. – LJM

0

Cố gắng này và nhận được

Loại hoặc namespace tên 'suối' không thể được tìm thấy (là bạn thiếu một chỉ thị sử dụng hoặc tham khảo một hội?) Không thể tìm thấy loại tên hoặc không gian tên 'StreamReader' (bạn thiếu một chỉ thị sử dụng hoặc tham chiếu assembly?) Không thể tìm thấy loại tên hoặc không gian tên 'StreamReader' (bạn thiếu một chỉ thị bằng cách sử dụng hoặc một assembly) tham khảo?) 'System.Net.Sockets.Socket' không chứa định nghĩa cho 'GetStream'

+1

xin tham khảo http://msdn.microsoft.com/en-us/library/system.io.stream.aspx – Aleyna

0
public string READS() 
    { 
     byte[] buf = new byte[CLI.Available];//set buffer 
     CLI.Receive(buf);//read bytes from stream 
     string line = UTF8Encoding.UTF8.GetString(buf);//get string from bytes 
     return line;//return string from bytes 
    } 
    public void WRITES(string text) 
    { 
     byte[] buf = UTF8Encoding.UTF8.GetBytes(text);//get bytes of text 
     CLI.Send(buf);//send bytes 
    } 

CLI là một ổ cắm. cho một số rezone lớp TcpClient không hoạt động ngay trên máy của tôi nữa, nhưng lớp Socket hoạt động tốt.

UTF-8 là mã hóa StreamReader/Writer bị khóa