Tôi có thể bỏ qua thứ tự byte trong mạng không?


24

Tôi đang phát triển một ứng dụng máy chủ-máy khách trong đó máy khách sẽ chạy trên Windows và máy chủ có thể trên Linux. Có thể sau này tôi sẽ chuyển máy khách sang Mac và Linux, nhưng chưa.

Tất cả các máy tính gia đình ngày nay chạy trên endian nhỏ. Tôi đã googled một thời gian, nhưng tôi thực sự không thể tìm thấy một danh sách các thiết bị chạy trên big endian. Theo tôi biết, một số chip Motorola vẫn sử dụng một số điện thoại lớn và có thể một số điện thoại (tôi không có kế hoạch chuyển ứng dụng sang điện thoại thông minh, vì vậy điều này không quan trọng với tôi). Vì vậy, tại sao tôi lại sắp xếp lại các byte của mọi số nguyên, mọi ngắn, mọi float, double, v.v. để đọc viết , khi tôi đã biết rằng cả hai, máy chủ và máy khách đều chạy trên endian nhỏ?

Đó chỉ là công việc không cần thiết phải làm. Vì vậy, câu hỏi của tôi là: Tôi có thể bỏ qua an toàn về endian và chỉ gửi dữ liệu endian nhỏ không? Những bất lợi là gì?


4
Làm thế nào các máy sẽ biết nếu chúng nhận được dữ liệu cuối nhỏ thay vì dữ liệu cuối lớn thông thường / tiêu chuẩn?
Ixrec

2
Bạn cần phân biệt giữa siêu dữ liệu được yêu cầu bởi giao thức mạng và tải trọng chỉ là một bó byte chưa được giải thích cho mọi người ngoại trừ mã của bạn. Tôi hy vọng bạn không lăn chồng mạng của riêng bạn. Do đó, tôi cho rằng câu hỏi chỉ là về tải trọng, đúng không?

2
@delnan có, chỉ nói về tải trọng. Tất nhiên tôi vẫn sẽ nói chuyện trong thứ tự byte mạng với chính ngăn xếp mạng.
tkausl

3
Chỉ cần một ý nghĩ ở bên: Có thực sự cần thiết cho bạn để làm việc ở mức độ trừu tượng trong đó tính bền vững là một mối quan tâm? Có thể đáng để xem xét sử dụng các giao thức cho các thư viện phù hợp tồn tại, gói gọn tất cả "mớ hỗn độn" cấp thấp này. Sau đó, bạn cũng có phần thưởng bổ sung rằng việc thêm khách hàng có thể được thực hiện dễ dàng hơn nhiều.
godfatherofpolka

1
@tkausl Chỉ cần thêm hai suy nghĩ nữa: Theo nguyên tắc chung, IO rất chậm so với tính toán, do đó, bất kỳ chi phí nào được giới thiệu bằng cách làm việc ở mức độ trừu tượng cao hơn rất có thể không đáng kể. Thậm chí có thể xảy ra việc một số thư viện vượt trội so với triển khai được kiểm soát do tổng hợp tài nguyên thông minh và xử lý không đồng bộ, v.v. Vì vậy, trước tiên tôi sẽ đánh giá cẩn thận các giải pháp hiện có. Hơn nữa, với mô tả của bạn, tôi cũng sẽ dành một số suy nghĩ về khả năng mở rộng thay vì hiệu suất, ở đây bạn có thể một lần nữa được hưởng lợi từ việc sử dụng các giao thức cấp cao hơn.
godfatherofpolka

Câu trả lời:


29

... tại sao tôi lại sắp xếp lại các byte ... khi tôi đã biết rằng cả máy chủ và máy khách đều chạy trên endian nhỏ? Đó chỉ là công việc không cần thiết để làm.

Nó chỉ không cần thiết nếu bạn có thể đảm bảo mã của bạn sẽ luôn chạy trên các kiến ​​trúc nhỏ về cuối. Nếu bạn dự định để nó có một cuộc sống lâu dài, thì đáng để nỗ lực thêm để tránh làm xáo trộn mã được chứng minh tốt trong một thập kỷ kể từ bây giờ khi một số kiến ​​trúc lớn đã trở thành một thứ "trong" và bạn thấy nó là một thị trường tốt cho ứng dụng của bạn.

Có một thứ tự byte tiêu chuẩn mạng. Đó là kết thúc lớn, nhưng không có gì nói rằng bạn phải tuân theo nó khi thiết kế giao thức của bạn. Nếu bạn biết trước phần lớn các hệ thống đang chạy mã của bạn sẽ rất ít về cuối và hiệu suất là rất quan trọng, hãy tuyên bố rằng "thứ tự byte tiêu chuẩn tkausl" và đi theo nó. Nơi bạn thường gọi htons()để sắp xếp mọi thứ theo thứ tự bạn cần, hãy viết một macro được gọi làhtots() điều kiện có thể biên dịch thành không có gì trên các kiến ​​trúc cuối nhỏ và sắp xếp lại trên endian lớn.

Duy trì mã để thực hiện chuyển đổi trong và ngoài nước thực sự không phải là một nỗ lực lớn. Nếu bạn có số lượng tin nhắn rất lớn, hãy tìm cách thể hiện chúng và viết chương trình để tạo chuyển đổi trong và ngoài nước.


10
Từ ngữ when designing your protocolrất quan trọng, bởi vì nó cũng ngầm nói rằng tùy chọn này chỉ tồn tại khi thiết kế một giao thức mới chứ không phải khi thực hiện một số giao thức hiện có. Và đề cập đến sự cần thiết của một htots(và thực sự là toàn bộ họ hàm), cũng cho thấy rõ rằng việc chọn một thứ tự byte khác nhau không phải là một cách để làm cho mã đơn giản hơn, nhưng nó có thể làm cho nó nhanh hơn một chút.
kasperd

4
Có (phi tiêu chuẩn nhưng rất phổ biến những ngày này) chức năng htole32(), htole16(), le16toh()vv, các chức năng có sẵn là tốt. Các tập tin để bao gồm để có được những tuyên bố này không may là thậm chí ít tiêu chuẩn hơn: <endian.h>hoặc <sys/types.h>tùy thuộc vào nền tảng.

Câu trả lời này là tốt, nhưng tôi nghĩ rằng giả định rằng hiệu suất có thể rất quan trọng trong trường hợp cụ thể có lẽ là một giả định sai, dựa trên sự mê tín nhiều hơn là sự thật.
Doc Brown

1
@DocBrown: Tôi luôn muốn chỉ ra rằng giao thức X đã hỗ trợ chọn thứ tự byte của riêng bạn trong 30 năm và chặt chẽ như tài nguyên đã trở lại sau đó, không ai phàn nàn rằng đó là một vấn đề.
Blrfl

7

Đó là giao thức của bạn.

Bạn không thể bỏ qua nó một cách an toàn. Nhưng bạn có thể dán nhãn nó một cách an toàn. Bạn điều khiển máy khách và máy chủ. Bạn điều khiển giao thức. Không có nghĩa gì nếu không quan tâm liệu đó là endian lớn hay endian nhỏ miễn là bạn biết liệu cả hai bên có đồng ý không?

Điều này có nghĩa là trên đầu. Bây giờ bạn phải đánh dấu endianness của bạn bằng cách nào đó. Làm điều đó, và tôi có thể đọc nó trên bất cứ điều gì.

Nếu bạn không muốn chi phí dữ liệu và CPU của bạn chán và tìm kiếm một cái gì đó để làm, thì hãy tuân thủ .


6

Vì vậy, câu hỏi của tôi là: Tôi có thể bỏ qua an toàn cho endianess và chỉ gửi dữ liệu endian nhỏ không?

Có hai cách hiểu về điều đó:

  • Nếu bạn thiết kế các ứng dụng / giao thức của mình để luôn gửi 1 endian nhỏ, thì bạn KHÔNG bỏ qua endianess.

  • Nếu bạn thiết kế các ứng dụng / giao thức của mình để gửi / nhận bất cứ thứ gì là endianess gốc, thì chúng sẽ hoạt động miễn là bạn chạy các ứng dụng của mình trên các nền tảng có cùng endianess.

    Có "an toàn" 2 không không? Đó là để bạn đánh giá! Nhưng chắc chắn có những nền tảng phần cứng phổ biến sử dụng ít endian, big endian hoặc ... bi-endian.

    Tài liệu tham khảo:

Những bất lợi là gì?

Nhược điểm rõ ràng của việc bỏ qua endianess là nếu bạn / người dùng của bạn cần chạy các ứng dụng / giao thức giữa các nền tảng với endianess khác nhau, thì bạn có vấn đề. Các ứng dụng sẽ bị hỏng và bạn sẽ cần thay đổi chúng để khắc phục sự cố. Và giải quyết các vấn đề tương thích phiên bản, vân vân.

Rõ ràng, hầu hết các nền tảng thế hệ hiện tại thực sự là ít endian, nhưng 1) một số thì không, và 2) chúng ta chỉ có thể đoán những gì sẽ xảy ra trong tương lai.


1 - Luôn luôn ... bao gồm cả trên các nền tảng thực sự lớn.

2 - Thật vậy, "an toàn" có nghĩa là gì? Nếu bạn đang yêu cầu chúng tôi dự đoán hướng phát triển của các nền tảng phần cứng trong tương lai ... Tôi e rằng điều đó không thể trả lời một cách khách quan.


3

Endianness không phải là sự cân nhắc duy nhất. Có kích thước của số nguyên, có đóng gói các cấu trúc mà bạn có thể muốn gửi hoặc nhận, v.v.

Bạn có thể bỏ qua tất cả điều này. Không ai có thể ép buộc bạn. Mặt khác, cách an toàn và đáng tin cậy là ghi lại một định dạng bên ngoài, sau đó viết mã sẽ đọc hoặc viết định dạng bên ngoài một cách chính xác, bất kể bộ xử lý, ngôn ngữ lập trình của bạn và việc thực hiện ngôn ngữ lập trình của bạn là gì.

Thông thường nó không có nhiều mã. Nhưng nó có một lợi ích rất lớn: Những người đọc mã của bạn sẽ không nghi ngờ rằng bạn không biết gì, không biết gì về việc trao đổi dữ liệu bên ngoài và viết mã thường không thể tin cậy được.


3

Ngăn xếp mạng BSD tiêu chuẩn trong C có hton/ ntohchức năng ( network-to-host/host-to-network ) mở rộng thành no-op trên các máy gốc mạng (endian lớn). Bạn sẽ cần các đối tác của riêng mình cho các kịch bản này trong trường hợp thứ tự byte gốc của mạng là ít về cuối.

Đó là cách mạnh mẽ để làm điều đó.

Nó là độc đáo, nhưng tôi thấy không có gì sai với nó. Các máy tính nối mạng luôn nhận được bytestream và chúng cần thống nhất các giao thức về cách diễn giải các byte đó. Đây chỉ là một phần của nó.


3

Các giao thức khác nhau được sử dụng để truyền dữ liệu giữa các máy chủ sử dụng các số cuối nhỏ:

  1. BSON
  2. Bộ đệm giao thức
  3. Capn Proto

Xem https://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats , để biết chi tiết về các định dạng khác nhau, một số trong số đó có số cuối nhỏ và một số có số cuối lớn.

Hoàn toàn không có gì sai khi sử dụng một giao thức dựa trên số lượng endian nhỏ. Một cỗ máy endian lớn có khả năng đọc các số endian nhỏ như một cỗ máy endian nhỏ có thể đọc các số endian lớn. Nhiều người đã thực hiện nó một cách cụ thể để tránh chi phí tính toán thêm khi giải mã các số lớn về cuối trên các máy cuối nhỏ.

Nếu bạn xây dựng giao thức của mình trên một trong những giao thức hiện có, thì bạn thậm chí không phải lo lắng về vấn đề này, nó đã được xử lý. Khi bạn quyết định chạy mã của mình trên nền tảng lớn, thì các thư viện triển khai các giao thức này sẽ tự động đảm bảo rằng bạn giải mã chính xác các giá trị.


2

Một ví dụ về một hệ thống endian lớn là MIPS được sử dụng trong các bộ định tuyến. Cả ARM và MIPS đều có thể chuyển đổi về cuối, nhưng MIPS thường là endian lớn vì nó giúp phần cứng mạng dễ dàng hơn (phần quan trọng nhất của từ là phần bạn nhận được trước và có thể đưa ra quyết định định tuyến trước khi bạn nhận được phần còn lại của từ, thay vì phải đệm toàn bộ từ).

Vì vậy, nó phụ thuộc vào ý nghĩa của bạn về 'Linux', nhưng nếu bạn muốn chạy ứng dụng máy chủ của mình trên một hệ thống nhỏ hơn như bộ định tuyến chạy OpenWRT thì bạn có thể phải xem xét hỗ trợ lớn về cuối.

Như thường lệ, thực hiện các giả định đơn giản hóa là một tối ưu hóa hoàn toàn hợp lý cho đến khi bạn đạt được điều gì đó không phù hợp với các giả định. Chỉ có bạn có thể nói sẽ đau đớn thế nào khi thư giãn chúng nếu bạn gặp phải một vấn đề như vậy.


0

Tôi không nghĩ bất kỳ câu trả lời nào là khá chính xác. Theo Wikipedia endianness là thứ tự byte bao gồm một từ.

Hãy lấy 4 byte và giải thích chúng là một int. Một hệ thống endian nhỏ, các byte sẽ được giải thích từ phải sang trái và ngược lại trên một hệ thống endian lớn. Rõ ràng điều quan trọng là phải đồng ý về kết thúc nào để giải thích một int.

Cho phép thu nhỏ một chút các giao thức mạng hiện đại có thể sử dụng json hoặc xml. Không có định dạng nào trong số đó sẽ chuyển một int là 4 byte. Họ sẽ chuyển dữ liệu dưới dạng văn bản sẽ được phân tích cú pháp dưới dạng int ở phía bên nhận.

Vì vậy, cuối cùng, endianness không thành vấn đề khi sử dụng json hoặc xml. Chúng ta vẫn cần sử dụng endian lớn cho các tiêu đề tcp, đó là lý do tại sao nó được gọi là thứ tự byte mạng, nhưng hầu hết các lập trình viên không cần phải làm phiền với những tiêu đề hàng ngày.

Mã hóa được sử dụng rộng rãi nhất hiện nay là utf-8, có khả năng miễn dịch với các vấn đề liên quan đến tuổi thọ .

Vì vậy, tôi sẽ nói có. Sẽ an toàn khi bỏ qua endianness khi sử dụng các định dạng dựa trên văn bản được truyền bằng utf-8.


hai phiếu giảm và không có ý kiến. Tuyệt quá.
Esben Skov Pedersen

1
Tôi không phải là người phản đối nhưng câu trả lời này dường như đang bỏ qua / bỏ qua một câu hỏi hoàn toàn hợp lệ. Chỉ vì một số giao thức dựa trên văn bản không có nghĩa là tất cả các giao thức nên có.
Peter Green

2
Tôi ủng hộ điều này bởi vì nó chạm vào thực tế là định dạng tải trọng không liên quan gì đến các giao thức cơ bản. Một số người chỉ thích đào sâu vào các vấn đề trang điểm.
Zdenek

0

Các hệ thống endian lớn dường như đang trên đường ra. Nhiều unixes truyền thống đã sử dụng endian lớn nhưng chúng đã bị suy giảm trong nhiều năm qua ủng hộ linux trên x86.

cánh tay là bi-endian nhưng biến thể endian lớn dường như hiếm thấy.

mips tồn tại trong cả hai biến thể. Afaict biến thể endian lớn chủ yếu được nhìn thấy trên các ứng dụng mạng (vì lý do lịch sử các giao thức internet thường sử dụng endian lớn).

ppc theo truyền thống là endian lớn với một số phần hỗ trợ cả hai endian nhưng IBM dường như đang đẩy chế độ endian nhỏ cho ppc 64 bit (gần đây họ đã đẩy các cổng ppc64el vào Debian và Ubuntu).

sparc thường là endian lớn nhưng một lần nữa dường như đang suy giảm.

Nếu bạn đang thực hiện một giao thức hiện có thì rõ ràng bạn phải tuân theo các thông số kỹ thuật của nó. Nếu bạn muốn IETF ban phước cho giao thức mới của mình thì endian lớn có thể sẽ dễ dàng hơn bởi vì đó là những gì họ đã sử dụng trong các giao thức hiện tại của họ, nhưng IMO cho một thiết kế cuối cùng được thiết kế theo kiểu "trường xanh" mới.

Bạn có thể đặt macro từ đầu, sẽ không hoạt động trên các hệ thống endian nhỏ hoặc bạn không thể làm phiền cho đến khi / trừ khi bạn cần chuyển sang hệ thống endian lớn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.