2010-03-03 37 views
11

Gần đây, khi đọc một Socket Programming HOWTO phần sau nhảy ra khỏi tôi:Ổ cắm Nghị định thư Fundamentals

Nhưng nếu bạn có kế hoạch để tái sử dụng ổ cắm của bạn để chuyển tiếp, bạn cần phải nhận ra rằng không có "EOT" (Kết thúc chuyển) trên một ổ cắm. Tôi lặp lại: nếu một socket gửi hoặc recv trả về sau khi xử lý 0 byte, kết nối đã bị hỏng. Nếu kết nối không bị hỏng, bạn có thể chờ đợi trên recv mãi mãi, bởi vì các ổ cắm sẽ không cho bạn biết rằng không có gì nhiều hơn để đọc (cho bây giờ). Bây giờ nếu bạn nghĩ về điều đó một chút, bạn sẽ nhận ra một sự thật cơ bản của ổ cắm: tin nhắn phải là chiều dài cố định (yuck), hoặc là được phân cách (nhún vai) hoặc cho biết thời gian là (tốt hơn), hoặc kết thúc bằng cách tắt kết nối. Sự lựa chọn là hoàn toàn của bạn, (nhưng một số cách là righter hơn những người khác).

Phần này nêu bật 4 khả năng về cách giao thức socket "có thể được viết để truyền thông điệp. Câu hỏi của tôi là, phương pháp ưa thích để sử dụng cho các ứng dụng thực tế là gì?

Nói chung là tốt nhất để bao gồm kích thước thư với mỗi thư (có lẽ trong tiêu đề), vì bài viết nhiều hay ít khẳng định? Có bất kỳ tình huống nào mà phương pháp khác sẽ thích hợp hơn không?

+0

Liên kết ở trên bị hỏng. – cdosborn

+0

Đó là về lập trình socket python, liên kết mới là https://docs.python.org/2/howto/sockets.html –

Trả lời

5

Các giao thức phổ biến hoặc chỉ định độ dài trong tiêu đề hoặc được phân tách (chẳng hạn như HTTP chẳng hạn).

Hãy nhớ rằng điều này cũng tùy thuộc vào việc bạn sử dụng ổ cắm TCP hay UDP. Vì ổ cắm TCP là đáng tin cậy, bạn có thể chắc chắn rằng bạn nhận được tất cả mọi thứ bạn đẩy vào chúng. Với UDP, câu chuyện khác và phức tạp hơn.

+0

+1, với chiều dài cố định UDP là cách để đi. Nếu bạn không phù hợp với mọi thứ trong một gói, bạn có thể không thể kết hợp lại với nhau. –

+1

Tại sao điều đó lại quan trọng, lớp IP sẽ không chuyển tiếp gói UDP tới ứng dụng của bạn nếu nó bị rên rỉ trên đường đi - phần còn thiếu của nó giống như thiếu tất cả, đúng không? Đã lâu rồi kể từ khi tôi viết một ứng dụng mạng, tôi sợ. –

+2

"Vì ổ cắm TCP là đáng tin cậy, bạn có thể chắc chắn rằng bạn nhận được tất cả mọi thứ bạn đẩy vào chúng" là một quan niệm sai lầm khủng khiếp. Bạn có thể chắc chắn rằng bạn nhận được mọi thứ theo đúng thứ tự và luồng dữ liệu bắt đầu với những gì bạn thực sự muốn bắt đầu, nhưng bạn không bao giờ có thể chắc chắn liệu nó có kết thúc ở đâu được dự định kết thúc mà không sử dụng cấu trúc giao thức cấp ứng dụng xác định điều đó. –

2

Đây thực sự là lựa chọn của chúng tôi với TCP. Ví dụ: HTTP sử dụng kết hợp tùy chọn thứ hai, thứ ba và thứ ra (các dòng tiêu đề yêu cầu/phản hồi kết thúc dòng đôi mới, trong đó có thể chứa tiêu đề Content-Length hoặc cho biết mã hóa chunked hoặc có thể nói Connection: close và không cung cấp chiều dài nội dung nhưng bạn mong đợi bạn dựa vào việc đọc EOF.)

Tôi thích tùy chọn thứ ba, tức là thông điệp tự mô tả, mặc dù chiều dài cố định là dễ dàng khi thích hợp.

1

Tôi không biết nếu có tùy chọn ưu tiên. Trong tình huống thực tế của chúng tôi (ứng dụng máy khách), chúng tôi sử dụng tùy chọn gửi tổng chiều dài tin nhắn là một trong những phần dữ liệu đầu tiên. Nó đơn giản và hoạt động cho cả việc triển khai TCP và UDP của chúng tôi. Nó làm cho logic hợp lý "đơn giản" khi đọc dữ liệu trong cả hai tình huống. Với TCP, số lượng mã là khá nhỏ (bằng cách so sánh). Phiên bản UDP hơi phức tạp (ít phức tạp) nhưng vẫn dựa vào kích thước được truyền trong gói ban đầu để biết khi nào tất cả dữ liệu đã được gửi đi.

+0

Một lựa chọn tốt. Việc thực hiện có thể dễ bị tràn bộ đệm khi các lập trình viên không kiểm tra với các thông báo không hợp lệ. –

2

Nếu bạn đang thiết kế giao thức của riêng mình thì hãy xem xét công việc của người khác trước; có thể đã có một cái gì đó tương tự ra khỏi đó mà bạn có thể sử dụng 'như là' hoặc tái sử dụng và điều chỉnh. Ví dụ; ISO-8583 cho txns tài chính, HTTP hoặc POP3 tất cả làm mọi thứ khác nhau nhưng theo cách được chứng minh là có hiệu quả ... Trong thực tế, bạn nên tìm hiểu những điều này như bạn sẽ học được rất nhiều về các giao thức thế giới thực.

Nếu bạn cần phải viết giao thức riêng của mình thì IMHO, thích các thông điệp có tiền tố dài hơn nếu có thể.Họ dễ dàng và hiệu quả để phân tích cú pháp cho người nhận nhưng có thể khó khăn hơn để tạo ra nếu nó là tốn kém để xác định độ dài của dữ liệu trước khi bạn bắt đầu gửi nó.

1

Quyết định phải phụ thuộc vào dữ liệu bạn muốn gửi (nó là gì, nó được thu thập như thế nào). Nếu dữ liệu có độ dài cố định, thì các gói có độ dài cố định có thể sẽ là tốt nhất. Nếu dữ liệu có thể dễ dàng (không cần thoát) được chia thành các thực thể được phân tách thì việc phân định có thể là tốt. Nếu bạn biết kích thước dữ liệu khi bạn bắt đầu gửi mẩu dữ liệu, thì tiền tố len có thể còn tốt hơn nữa. Nếu dữ liệu được gửi luôn là các ký tự đơn hoặc thậm chí một bit (ví dụ: "bật"/"tắt") thì bất kỳ điều gì khác với kích thước cố định, một thông báo ký tự sẽ quá nhiều.

Cũng nghĩ cách thức giao thức có thể phát triển. Các chuỗi phân tách EOL là tốt miễn là chúng không chứa các ký tự EOL. Độ dài cố định có thể tốt cho đến khi dữ liệu có thể được mở rộng với một số phần tùy chọn, v.v.