2012-09-29 32 views
9

send() sẽ trả về số byte được gửi hoặc mã lỗi, nhưng tất cả các ví dụ mà tôi tìm thấy chỉ kiểm tra mã lỗi, nhưng không phải là số byte được gửi.Gửi() allways gửi toàn bộ bộ đệm?

//typical example 
int cnt=send(s,query,strlen(query),0); 
if (cnt < 0) return(NULL); 
//Hey, what about cnt < strlen(query)? 

Trả lời

13

Q: "send()" luôn trả về toàn bộ bộ đệm?

A: Không, không nhất thiết.

Từ Hướng dẫn Beej của: * http://beej.us/guide/bgnet/output/html/multipage/syscalls.html#sendrecv

send() trả về số byte thực sự được gửi ngoài này có thể ít hơn số bạn nói với nó để gửi ! Hãy xem, đôi khi bạn nói với nó để gửi toàn bộ dữ liệu và nó không thể xử lý được. Nó sẽ kích hoạt tắt càng nhiều dữ liệu càng tốt và tin tưởng bạn gửi phần còn lại sau đó. Hãy nhớ rằng, nếu giá trị được trả về bởi send() không khớp với giá trị trong len, bạn có thể gửi phần còn lại của chuỗi. Các tin tức tốt là điều này: nếu gói nhỏ (ít hơn 1K hoặc hơn) nó sẽ có thể quản lý để gửi toàn bộ điều tất cả trong một đi. Một lần nữa, -1 là trả lại do lỗi và errno được đặt thành số lỗi.

Q: "recv()" luôn đọc toàn bộ bộ đệm?

A: Không, hoàn toàn không. Bạn nên không bao giờ giả định bộ đệm bạn đã nhận được là "toàn bộ thư". Hoặc giả sử thư bạn nhận được từ một, duy nhất thư.

Đây là giải thích ngắn gọn, tốt. Đó là cho Microsoft/C#, nhưng nó áp dụng cho tất cả các ổ cắm I/O, trong bất kỳ ngôn ngữ:

+5

-1: Chính xác ngược - đối với mọi giao thức dựa trên luồng (chẳng hạn như TCP), gửi có thể trả về ít hơn số tiền được yêu cầu, nếu bộ đệm cục bộ gần như đã đầy từ các lần gửi trước đó. Đối với các giao thức datagram (như UDP), việc gửi sẽ không thành công hoặc gửi toàn bộ bộ đệm dưới dạng gói - không thể gửi một phần. –

+1

Tôi đã không bỏ phiếu, nhưng hãy xem câu trả lời của tôi, bạn đã sai. –

+0

@Kiril Kirov - bạn và Chris Dodd là hoàn toàn chính xác. Rắm não về phía tôi - xin lỗi. Tôi đã sửa chữa câu trả lời của mình. Cảm ơn bạn! – paulsm4

3

Không, nó không.

Để tham khảo, xem the man page for send:

Khi tin nhắn không phù hợp với send đệm của ổ cắm, send() thường khối, trừ khi ổ cắm đã được đặt trong nonblocking I/O mode. Ở chế độ không chặn, nó sẽ thất bại với lỗi EAGAIN hoặc EWOULDBLOCK trong trường hợp này. Cuộc gọi chọn (2) có thể được sử dụng để xác định khi nào có thể gửi nhiều dữ liệu hơn.

+0

Trang thủ công gây nhầm lẫn: nhận xét KHÔNG áp dụng cho các ổ cắm SOCK_STREAM, chỉ các loại khác. –

4

Câu trả lời là trong một phần khác của man 2 send:

When the message does not fit into the send buffer of the socket, 
    send() normally blocks, unless the socket has been placed in nonblock‐ 
    ing I/O mode. In nonblocking mode it would fail with the error EAGAIN 
    or EWOULDBLOCK in this case. The select(2) call may be used to deter‐ 
    mine when it is possible to send more data. 

Hoặc cách khác, phiên bản POSIX (man 3p send):

If space is not available at the sending socket to hold the message to 
    be transmitted, and the socket file descriptor does not have O_NONBLOCK 
    set, send() shall block until space is available. If space is not 
    available at the sending socket to hold the message to be transmitted, 
    and the socket file descriptor does have O_NONBLOCK set, send() shall 
    fail. The select() and poll() functions can be used to determine when 
    it is possible to send more data. 

Vì vậy, trong khi một read dữ liệu phần được phổ biến , không thể xảy ra một phần send trong chế độ chặn (chặn chi tiết triển khai).

+0

Trang hướng dẫn gây nhầm lẫn: nhận xét KHÔNG áp dụng cho ổ cắm SOCK_STREAM, chỉ các loại khác –

+0

Có một phần khác của định nghĩa Posix của hàm có liên quan - "Nếu thông báo quá dài để truyền qua giao thức cơ bản, hãy gửi () sẽ thất bại và không có dữ liệu nào được truyền đi ", đó là lý do tại sao bạn không nhận được gửi một phần trên UDP. –

Các vấn đề liên quan