UNIX Network Programming Volume 1, Third Edition [Electronic resources] : The Sockets Networking API نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

UNIX Network Programming Volume 1, Third Edition [Electronic resources] : The Sockets Networking API - نسخه متنی

Addison Wesley

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید










23.3 Partial Delivery


Partial delivery will be used by the SCTP implementation any time a "large" message is being received, where "large" means the SCTP stack deems that it does not have the resources to dedicate to the message. The following considerations will be made by the receiving SCTP implementation before starting this API:

  • The amount of buffer space being consumed by the message must meet or exceed some threshold.

  • The stack can only deliver from the beginning of the message sequentially up to the first missing piece.

  • Once invoked, no other messages may be made available for the user until the current message has been completely received and passed to the user. This means that the large message blocks all other messages that would normally be deliverable, including those in other streams.


The KAME implementation of SCTP uses a threshold of one-half the socket receive buffer. At this writing, the default receive buffer for the stack is 131,072 bytes. So, without changing the SO_RCVBUF, a single message must be larger than 65,536 bytes before the partial delivery API will be invoked. To further extend the new version of the server from Section 10.2, we write a utility function that wraps the sctp_recvmsg function call. We then create a modified server to use our new function. Figure 23.2 shows our wrapper function to handle the partial delivery API.


Prepare static buffer


1215 If the function's static buffer has not been allocated, allocate it and set up the state associated with it.


Read message


1618 Read in the first message using the sctp_recvmsg function.


Handle initial read error


1922 If sctp_recvmsg returns an error or an EOF, we pass it directly back to the caller.


While there is more data for this message


2324 While the message flags show that the function has not received a complete message, collect more data. The function starts by calculating how much is left in the static buffer.


See if we need to grow static buffer


2534 Whenever the function no longer has a minimum amount of room left in its receive buffer, it must grow the buffer. We do this using the realloc function to allocate a new buffer of the current size, plus an increment amount, and copy the old data. If for some reason the function cannot grow its buffer any more, it exits with an error.


Receive more data


3536 Gather more data with the sctp_recvmsg function.


Move forward


3738 The function increments the buffer index and goes back to test if it has read all of the message.


At loop end


3940 When the loop terminates, the function copies the number of bytes read into the pointer provided by the caller and returns a pointer to the allocated buffer.

Figure 23.2 Handling the partial delivery API.

sctp/sctp_pdapircv.c


1 #include "unp.h"
2 static uint8_t *sctp_pdapi_readbuf = NULL;
3 static int sctp_pdapi_rdbuf_sz = 0;
4 uint8_t *
5 pdapi_recvmsg(int sock_fd,
6 int *rdlen,
7 SA *from,
8 int *from_len, struct sctp_sndrcvinfo *sri, int *msg_flags)
9 {
10 int rdsz, left, at_in_buf;
11 int frmlen = 0;
12 if (sctp_pdapi_readbuf == NULL) {
13 sctp_pdapi_readbuf = (uint8_t *) Malloc(SCTP_PDAPI_INCR_SZ);
14 sctp_pdapi_rdbuf_sz = SCTP_PDAPI_INCR_SZ;
15 }
16 at_in_buf =
17 Sctp_recvmsg(sock_fd, sctp_pdapi_readbuf, sctp_pdapi_rdbuf_sz, from,
18 from_len, sri, msg_flags);
19 if (at_in_buf < 1) {
20 *rdlen = at_in_buf;
21 return (NULL);
22 }
23 while ((*msg_flags & MSG_EOR) == 0) {
24 left = sctp_pdapi_rdbuf_sz - at_in_buf;
25 if (left < SCTP_PDAPI_NEED_MORE_THRESHOLD) {
26 sctp_pdapi_readbuf =
27 realloc(sctp_pdapi_readbuf,
28 sctp_pdapi_rdbuf_sz + SCTP_PDAPI_INCR_SZ);
29 if (sctp_pdapi_readbuf == NULL) {
30 err_quit("sctp_pdapi ran out of memory");
31 }
32 sctp_pdapi_rdbuf_sz += SCTP_PDAPI_INCR_SZ;
33 left = sctp_pdapi_rdbuf_sz - at_in_buf;
34 }
35 rdsz = Sctp_recvmsg(sock_fd, &sctp_pdapi_readbuf[at_in_buf],
36 left, NULL, &frmlen, NULL, msg_flags);
37 at_in_buf += rdsz;
38 }
39 *rdlen = at_in_buf;
40 return (sctp_pdapi_readbuf);
41 }

We next modify our server in Figure 23.3 so that it uses the new function.


Read message


2930 Here the server calls the new partial delivery utility function. The server calls this after nulling out any old data that may have been hanging around in the sri variable.

Figure 23.3 Our server using the partial delivery API.

sctp/sctpserv05.c


26 for ( ; ; ) {
27 len = sizeof(struct sockaddr_in);
28 bzero(&sri, sizeof(sri));
29 readbuf = pdapi_recvmsg(sock_fd, &rd_sz,
30 (SA *) &cliaddr, &len, &sri, &msg_flags);
31 if (readbuf == NULL)
32 continue;


Verify we read something


3132 Note that now the server must test for NULL to see if the read was successful. If not, the server just continues.


/ 450