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 đỡ.

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

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

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

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

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

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.

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

1 Like

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ự.

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.

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.

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ỉ

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.

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?

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

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…

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

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.

1 Like

Đồ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

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???

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?