01/10/2018, 17:17

Chuyển byte[] sang UTF8.GetString bị thiếu message

mình có đoạn code chuyển string sang byte[] như sau:

public void Write(string input)
{
    // We need to know how many character the message have .
    Write(input.Length);
    buffer.AddRange(Encoding.UTF8.GetBytes(input));
}

và đoạn code lấy lại string:

public string ReadString(bool peek = true)
{
    int length = ReadInterger(peek);
    string value = Encoding.UTF8.GetString(readBuffer,ReadPosition,length);
    ReadPosition = (peek) ? ReadPosition += length : ReadPosition;
    return value;
}

và nó nhận thiếu message đoạn message như sau:

Tài khoản hoặc mật khẩu không chính xác.

nhưng khi dùng hàm ReadString nó chỉ nhận được:

Tài khoản hoặc mật khẩu không

mọi người có cách giải quyết nào cho vấn đề này vui lòng giúp đỡ.

Quân viết 19:27 ngày 01/10/2018

1 kí tự ở utf8 có thể tới 4byte. Còn khi đếm kí tự thì chỉ là 1

Harknes viết 19:29 ngày 01/10/2018

mình cũng nghĩ vậy. sau khi đọc song thì vẫn còn 12 byte trong mảng nữa.

Quân viết 19:28 ngày 01/10/2018

Vậy thì bạn có giải pháp fix rồi đấy

Harknes viết 19:22 ngày 01/10/2018

bắt buộc đọc hết mảng byte sao? không còn giải pháp khác.

Quân viết 19:31 ngày 01/10/2018

Bạn ghi số byte cần thiết để encode vào header thôi. Code gần như không đổi. Mà không đọc hết mảng byte thì sao đọc hết được msg hả bạn. Tự nhiên lại thấy hoang mang chỗ này

Harknes viết 19:19 ngày 01/10/2018

mình cảm ờn vì sự giúp đỡ. Vừa nhận ra vấn đề. Đoạn message trên là

Tài khoản hoặc mật khẩu không chính xác. và hàm length thông báo chỉ 40 ký tự.

Tai khoan hoac mat khau khong chinh xac. cũng dài 40 ký tự.

giờ ta biết là 12 byte còn lại chưa đọc là do các dấu câu. hàm length không thể nhận ra điều đó.
giờ ta có vấn đề mới làm sao để hàm length biết được trong câu có chứa ký tự unicode.

Quân viết 19:21 ngày 01/10/2018

Mình lại hỏi bạn tại sao hàm length phải biết điều đấy trong khi bạn đã có đoạn code này

Encoding.UTF8.GetBytes(input)

Trả về 1 mảng byte. Và nghiễm nhiên bạn cũng có thể lấy được cần bao nhiêu byte bằng cách lấy length của mảng byte đấy rồi. Sao bạn phải nghĩ đến cách gì cao siêu để giải quyết thế nhỉ.
PS: unicode hiện dùng 4byte cho 1 kí tự. Bất kể có dấu hay không dấu nên cho dù biết được là có kí tự unicode đi chăng nữa cũng không đếm đúng byte cho bạn ở encoding utf-8 được đâu

Quân viết 19:18 ngày 01/10/2018

Bạn tham khảo link này để biết thêm về text encoding. Tự suy ngẫm sẽ hiểu vì sao người ta không làm 1 method đếm byte của chuỗi kí tự.

en.wikipedia.org

Unicode

Unicode is a computing industry standard for the consistent encoding, representation, and handling of text expressed in most of the world's writing systems. The standard is maintained by the Unicode Consortium, and as of June 2018[update] the most recent version, Unicode 11.0, contains a repertoire of 137,439 characters covering 146 modern and historic scripts, as well as multiple symbol sets and emoji. The character repertoire of the Unicode Standard is synchronized with ISO/IEC 10646, and bot...

Harknes viết 19:22 ngày 01/10/2018

khi bạn gửi data qua mạng nó bao gồm command,id,position,rotation, nó không chỉ là 1 string. nó là tổ hợp của tất cả những thứ mà client cần để render nó lên.

Harknes viết 19:30 ngày 01/10/2018

dù sao thì mình cũng cảm ơn sự giúp đỡ của bạn. bạn không có cách giải quyết giúp mình rồi.

Quân viết 19:29 ngày 01/10/2018

Uh, thế thì có vấn đề gì nhỉ. Mình đoán nếu bạn đã viết được đến đây bằng method đếm length rồi thì việc align data cho các field kia bạn đã phải care ổn rồi chứ nhỉ

Quân viết 19:30 ngày 01/10/2018

Mình đoán bạn muốn 1 giải pháp ăn sẵn. Nếu thế thì xin lỗi, mình không giúp bạn được. Việc align data bạn không hề nhắc đến trong câu hỏi nên mình không care đến vấn đề đấy trong câu trả lời.
Vấn đề của bạn đã được giải quyết nếu bạn hiểu những gì mình nói. Hoặc có thể bạn đang cần 1 đoạn code chạy được cho bạn copy.

Harknes viết 19:26 ngày 01/10/2018

bạn sai rồi code mình chạy ngon. mình đang cần 1 giải pháp tốt hơn là việc lúc nào cũng đặt string ở cuối data. hãy nói với mình là bạn đã từng gửi data qua mạng?

Quân viết 19:18 ngày 01/10/2018

Thứ nhất, xin xác nhận là code bạn đang có logic bug chỗ ghi string. Không thể nói là chạy ngon được. Nhưng vấn đề đó tạm bỏ qua
Bây giờ code bạn bây giờ đang gặp vấn đề là phải đặt string ở cuối data thì mới có thể đọc được đúng không. Nếu đúng thì xin hãy xác nhận và nói rõ thông tin. Chứ đến hiện tại mình vẫn chưa rõ vấn đề mà bạn gặp ngoài việc bạn ghi sai length của độ dài 1 chuỗi cần ghi ở dạng byte

Tao Không Ngu. viết 19:32 ngày 01/10/2018

Hi nông văn tình
Theo mình thì giải pháp đóng thẳng dữ liệu vào chỉ là chữa cháy, ăn xổi. Thường thì mình thấy người ta thiết kế truyền thông có nhiều lớp để mã hóa giải mã đóng gói dữ liệu.

  1. Bạn cần truyền : command,id,position,rotation, nó không chỉ là 1 string -> cần dùng một gói tin có cấu trúc đóng đống dữ liệu này vào thường thì người ta dùng json. (Hoặc tự quy định khi đó nên dùng ByteBuffer)
  2. Sau khi bạn được một đối tượng json rồi thì việc tiếp là endcode nó ra mảng byte rồi đóng vào một gói tin data raw truyền đi với header là kích thước gói tin và id v.v.v…
  3. Khi đọc thì bạn đọc phần header để lấy thông tin gói tin raw kiểm tra gói tin v.v.v… sau đó lấy phần data mảng byte ra.
  4. Chuyển từ mảng byte thành Json rồi mới lấy dữ liệu.

Nghe có vẻ phức tạp tuy nhiên nó sẽ rõ rang khi thiết kế cũng như triển khai.

  1. Khi đóng gói vào json nó là chuẩn chung nên không cần viết lại có thể dùng cho n hiều nền tảng ngôn ngữ. Gói tin có cấu trúc có thể mở rộng.
  2. Các tằng truyền thông riêng biệt dễ debug, thay đổi code v.v.v… khả năng mở rộng cho dhuyền các loại dữ liệu khác như hình ảnh file v.v.v…
Quân viết 19:33 ngày 01/10/2018

Lowlevel network thì làm như bạn kia là ổn rồi. Nếu code tốt thì hiệu năng tốt hơn giải pháp dùng high level serialize như json hay các dạng khác. Nhưng sẽ code kiểu tay to. Có thể tham khảo protobuf thì sẽ đỡ cực hơn

Tao Không Ngu. viết 19:18 ngày 01/10/2018

Hi Quân.
Tất nhiên về mặt lý thuyết là như thế tuy nhiên theo mình thấy vấn đề khi truyền thống qua mạng là tốc độ mạng là cái chiếm nhiều thời gian nhất. Trừ các yêu cầu đặc thù ra còn không với lập trình thông thường thì cứ đóng gói tin theo chuẩn là cách đơn giản nhưng vẫn đáp ứng hiệu năng.

Quân viết 19:21 ngày 01/10/2018

Đồng ý, nếu không có yêu cầu đặc biệt thì nên chọn cách mà bạn đưa ra sẽ đảm bảo cho việc maintain sau này được dễ dàng hơn. Còn nếu muốn tự code để hiểu thì cứ code thôi. Hehe. Với bài của bạn này gần như đã đến được đích rồi không biết còn tiếp tục không

Harknes viết 19:24 ngày 01/10/2018

lợi ích mà bạn nêu là rất lớn. Vấn đề là game thời gian thực mình muốn Convert sang byte[] và gửi đi ngay lập tức. Latency???

Tao Không Ngu. viết 19:20 ngày 01/10/2018

Hi nông văn tình.
Mình không biết bạn làm game thời gian gì mà cần truyền cả dữ liệu có dấu thời gian thức vậy ??? Thường thì thấy các dữ liệu quan trong như tọa độ ngừời chơi, skill dùng mới được truyền qua kênh ưu tiên còn các dữ liệu khác như tên, thông tin, v.v.v… thì dùng các kênh chậm hơn đảm bảo phân tải giảm gánh nặng cho server game khi phải chạy logic game (64-128 tick).

Bài liên quan
0