Tôi đã chạy vào những gì tôi tin là một vấn đề với phương thức BinaryReader.ReadChars(). Khi tôi quấn một BinaryReader xung quanh một ổ cắm nguyên NetworkStream đôi khi tôi nhận được một dòng tham nhũng, nơi dòng được đọc được ra khỏi đồng bộ. Luồng được đề cập chứa các thông điệp trong giao thức tuần tự nhị phân.Vấn đề với BinaryReader.ReadChars()
Tôi đã theo dõi này xuống sau
- Nó chỉ xảy ra khi đọc một chuỗi unicode (được mã hóa bằng cách sử dụng Encoding.BigEndian)
- Nó chỉ xảy ra khi chuỗi trong câu hỏi được chia giữa hai gói tcp (xác nhận sử dụng Wireshark)
tôi nghĩ rằng những gì đang xảy ra là như sau (trong bối cảnh các ví dụ dưới đây)
- BinaryReader.ReadChars() được gọi là yêu cầu đọc 3 ký tự (độ dài chuỗi được mã hóa trước chính chuỗi đó)
- Vòng lặp đầu tiên yêu cầu đọc 6 byte (3 ký tự còn lại * 2 byte/char) dòng mạng
- mạng suối chỉ có 3 byte sẵn
- 3 byte đọc vào bộ đệm địa phương
- buffer giao cho bộ giải mã
- decoder giải mã 1 char, và giữ byte khác trong nó đệm nội bộ riêng
- Second lặp lại nội bộ nhiệm vụ đọc 4 byte! (2 ký tự còn lại * 2 byte/char)
- dòng Mạng có tất cả 4 byte sẵn
- 4 byte đọc vào bộ đệm địa phương
- Buffer giao cho bộ giải mã
- Decoder giải mã 2 char, và giữ các byte thứ 4 còn lại trong nội bộ
- Giải mã chuỗi hoàn tất
Mã tuần tự cố gắng loại trừ mục và mục tiếp theo do lỗi gián đoạn luồng.
char[] buffer = new char[3]; int charIndex = 0; Decoder decoder = Encoding.BigEndianUnicode.GetDecoder(); // pretend 3 of the 6 bytes arrives in one packet byte[] b1 = new byte[] { 0, 83, 0 }; int charsRead = decoder.GetChars(b1, 0, 3, buffer, charIndex); charIndex += charsRead; // pretend the remaining 3 bytes plus a final byte, for something unrelated, // arrive next byte[] b2 = new byte[] { 71, 0, 114, 3 }; charsRead = decoder.GetChars(b2, 0, 4, buffer, charIndex); charIndex += charsRead;
Tôi nghĩ gốc là một lỗi trong mã NET trong đó sử dụng charsRemaining * byte/char mỗi vòng lặp để tính toán các byte còn lại được yêu cầu. Vì byte thừa được ẩn trong Bộ giải mã nên việc tính toán này có thể bị tắt bởi một byte gây ra thêm byte được tiêu thụ ngoài luồng đầu vào.
Dưới đây là .NET framework đang trong câu hỏi
while (charsRemaining>0) {
// We really want to know what the minimum number of bytes per char
// is for our encoding. Otherwise for UnicodeEncoding we'd have to
// do ~1+log(n) reads to read n characters.
numBytes = charsRemaining;
if (m_2BytesPerChar)
numBytes <<= 1;
numBytes = m_stream.Read(m_charBytes, 0, numBytes);
if (numBytes==0) {
return (count - charsRemaining);
}
charsRead = m_decoder.GetChars(m_charBytes, 0, numBytes, buffer, index);
charsRemaining -= charsRead;
index+=charsRead;
}
Tôi không hoàn toàn chắc chắn nếu điều này là một lỗi hay chỉ là một sự lạm dụng của API. Để làm việc vòng vấn đề này tôi chỉ tính toán các byte yêu cầu bản thân mình, đọc chúng, và sau đó chạy byte [] thông qua Encoding.GetString() có liên quan. Tuy nhiên điều này sẽ không làm việc cho một cái gì đó như UTF-8.
Hãy quan tâm để nghe suy nghĩ của mọi người về điều này và liệu tôi có đang làm điều gì đó sai hay không. Và có lẽ nó sẽ tiết kiệm cho người tiếp theo một vài giờ/ngày của tẻ nhạt tẻ nhạt.
CHỈNH SỬA: được đăng để kết nối Connect tracking item
Làm cho tôi băn khoăn tại sao BinaryReader thậm chí có phương pháp ReadChars. Toàn bộ điểm của BinaryReader là đọc dữ liệu nhị phân, không phải dữ liệu văn bản. Tôi nghĩ điều đúng đắn cần làm là sử dụng các lớp mã hóa như bạn đã nói. – Josh
Không chắc chắn, đoán nó đang cố gắng để được một mục đích chung Reader chuyển đổi từ nhị phân thành các loại nguyên thủy cơ bản (int, dài, chuỗi vv). Tôi nghĩ rằng cách tiếp cận tốt nhất tổng thể, mà sẽ làm việc cho UTF-8 quá, là để mã hóa số byte (chứ không phải là ký tự) ở phía gửi và sau đó làm một byte [] đọc + Mã hóa cuộc gọi. –