關(guān)于IOCP中是否可以對(duì)同一socket連續(xù)投遞的疑問已經(jīng)很久了,主要的疑問在wsaSend是否可以保證數(shù)據(jù)的完整發(fā)送,是否會(huì)出現(xiàn)部分發(fā)送成功的情況? 網(wǎng)上大多數(shù)的建議都是WSASEND采用線性模式,即建立一個(gè)發(fā)送緩沖,當(dāng)上一次send完成之后,再進(jìn)行下一次的投遞。那么WSASEND什么情況下會(huì)出現(xiàn)部分發(fā)送呢? 在MSDN中IOCP的列子是對(duì)得到的發(fā)送的字節(jié)值進(jìn)行了判斷的,而在wsaSend函數(shù)的描述中也有這樣一句:Note The successful completion of a WSASend does not indicate that the data was successfully delivered. 我首先想到的是當(dāng)發(fā)送緩沖區(qū)不足的時(shí)候,會(huì)不會(huì)造成wsaSend部分發(fā)送返回。做了個(gè)實(shí)驗(yàn),連續(xù)發(fā)送10M的數(shù)據(jù)(肯定大于緩沖區(qū)了)。第一次直接返回成功(對(duì)端并未進(jìn)行Recv),第二次返回IO_PENDING.看來不是這樣的。查了《windows 網(wǎng)絡(luò)編程技術(shù)》其中有這樣一段話: When an application makes a send call, if there is sufficient buffer space, the data is copied into the socket's send buffers, the call completes immediately with success, and the completion is posted. On the other hand, if the socket's send buffer is full, then the application's send buffer is locked and the send call fails withWSA_IO_PENDING. After the data in the send buffer is processed (for example, handed down to TCP for processing), then Winsock will process the locked buffer directly. That is, the data is handed directly to TCP from the application's buffer and the socket's send buffer is completely bypassed。 當(dāng)發(fā)送緩沖不足的時(shí)候,會(huì)內(nèi)存鎖定,我另一端調(diào)用recv,收到wsasend的完成信號(hào)時(shí),發(fā)送的字節(jié)數(shù)=要發(fā)送的字節(jié)數(shù),并沒有部分發(fā)送。 下面是我網(wǎng)上找到的一片帖子忘了出自哪里了。 --------------------------------------------------------------------------------------------------------- 對(duì)于WSASend使用,一直有些疑惑,雖然對(duì)開發(fā)影響不大,但是總是很別扭。
看來WSASend是在把請(qǐng)求放入TCB隊(duì)列就返回了。Google過一些英文網(wǎng)站,得到類似的回答 Actually,
a partial overlapped send guarantees all subsequently 再看MSDN 有這樣一段話 For non-overlapped sockets, the last two parameters (lpOverlapped,lpCompletionRoutine) are ignored and WSASend adopts the same blocking semantics assend. Data is copied from the buffer(s) into the transport's buffer. If the socket is non-blocking and stream-oriented, and there is not sufficient space in the transport's buffer,WSASend will return with only part of the application's buffers having been consumed. Given the same buffer situation and a blocking socket,WSASend will block until all of the application buffer contents have been consumed. 之前的理解有誤,這段話應(yīng)該聯(lián)合起來理解,對(duì)于未使用overlapped的socket,最后兩個(gè)參數(shù)是被忽略的 這時(shí)候wsasend表現(xiàn)就和send一樣,數(shù)據(jù)被拷貝到發(fā)送緩沖區(qū),在這種情況下(wsasend像send) 如果是面向流的nonblockingmodel的套接字 并且發(fā)送緩沖區(qū)不足的情況下,wsasend返回拷貝到發(fā)送緩沖區(qū)的字節(jié)數(shù),如果是blocking socket wsasend知道發(fā)送完畢才返回。(這個(gè)行為和send是一致的,也就是只有在這種情況下wsaSend才會(huì)部分發(fā)送) 什么是non-overlapped sockets?之前一直把non-overlapped sockets 當(dāng)做blocking socket . 再看windows網(wǎng)絡(luò)編程 Blocking sockets cause concern because any Winsock API call on a blocking socket can do just that—block for some period of time. Most Winsock applications follow a producer-consumer model in which the application reads (or writes) a specified number of bytes and performs some computation on that data. Once a socket is placed in non-blocking mode, Winsock API calls that deal with sending and receiving data or connection management return immediately. In most cases, these calls fail with the error WSAEWOULDBLOCK, which means that the requested operation did not have time to complete during the call. For example, a call torecv returns WSAEWOULDBLOCK if no data is pending in the system's input buffer. Often additional calls to the same function are required until it encounters a successful return code No –Blocking socket是不同于non-overlapped socket 之前對(duì)于overlap的理解還是有些誤區(qū) 現(xiàn)在的理解是 overlap是一種異步使用方式 與block no blocking 不是一個(gè)感念。 overlapIO不只是socket,還包括readfile等等同樣iocp對(duì)應(yīng)的也不只nonblockingsocket而是 overlapIO Overlapped sockets merely means that you can use the sockets for overlapped IO. It doesn't mean that your socket is non-blocking. 完成端口和重疊IO的例子都沒有指定socket必須是non-blocking socket. non-blocking socket 是指不滿足當(dāng)前條件的情況下 返回,當(dāng)滿足當(dāng)前需求,還是操作完成才返回,例如將發(fā)送緩沖區(qū)填滿。 而overlap socket是只要當(dāng)前情況不能立即執(zhí)行完畢 便會(huì)返回pending 也就是說 在發(fā)送緩沖區(qū)填滿前就已經(jīng)返回了。
在我自己的測(cè)試程序中 我把發(fā)送和接受緩沖區(qū)大小都設(shè)置為了0 所以每次發(fā)送返回都是peding,系統(tǒng)鎖定發(fā)送緩沖,當(dāng)發(fā)送完成后得到完成通知。
所以重疊IO和完成IO 與block socket non blocking socket 是兩碼事 ,我接下來測(cè)試下用blocksocket 與non blockingsocket 在iocp上有什么影響 ,個(gè)人現(xiàn)在感覺應(yīng)該是一樣的。(經(jīng)過測(cè)試 用blocking socket iocp仍可正常工作,單non-overlapped socket不行 默認(rèn)的socket()創(chuàng)建出的是支持overlapped的) 現(xiàn)在的系統(tǒng)使用non-blocking socket必須使用overlap模式
沒想到這篇文章寫了一年之后才來更新 呵呵 寫的比較亂 原諒 |
|