亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? advanced.html

?? Beej的socket教材
?? HTML
?? 第 1 頁 / 共 2 頁
字號:
        myaddr.sin_addr.s_addr = INADDR_ANY;        myaddr.sin_port = htons(PORT);        memset(&#38;(myaddr.sin_zero), '\0', 8);        if (bind(listener, (struct sockaddr *)&#38;myaddr, sizeof(myaddr)) == -1) {            perror("bind");            exit(1);        }        // listen        if (listen(listener, 10) == -1) {            perror("listen");            exit(1);        }        // add the listener to the master set        FD_SET(listener, &#38;master);        // keep track of the biggest file descriptor        fdmax = listener; // so far, it's this one        // main loop        for(;;) {            read_fds = master; // copy it            if (select(fdmax+1, &#38;read_fds, NULL, NULL, NULL) == -1) {                perror("select");                exit(1);            }            // run through the existing connections looking for data to read            for(i = 0; i &#60;= fdmax; i++) {                if (FD_ISSET(i, &#38;read_fds)) { // we got one!!                    if (i == listener) {                        // handle new connections                        addrlen = sizeof(remoteaddr);                        if ((newfd = accept(listener, (struct sockaddr *)&#38;remoteaddr,                                                                 &#38;addrlen)) == -1) {                             perror("accept");                        } else {                            FD_SET(newfd, &#38;master); // add to master set                            if (newfd &#62; fdmax) {    // keep track of the maximum                                fdmax = newfd;                            }                            printf("selectserver: new connection from %s on "                                "socket %d\n", inet_ntoa(remoteaddr.sin_addr), newfd);                        }                    } else {                        // handle data from a client                        if ((nbytes = recv(i, buf, sizeof(buf), 0)) &#60;= 0) {                            // got error or connection closed by client                            if (nbytes == 0) {                                // connection closed                                printf("selectserver: socket %d hung up\n", i);                            } else {                                perror("recv");                            }                            close(i); // bye!                            FD_CLR(i, &#38;master); // remove from master set                        } else {                            // we got some data from a client                            for(j = 0; j &#60;= fdmax; j++) {                                // send to everyone!                                if (FD_ISSET(j, &#38;master)) {                                    // except the listener and ourselves                                    if (j != listener &#38;&#38; j != i) {                                        if (send(j, buf, nbytes, 0) == -1) {                                            perror("send");                                        }                                    }                                }                            }                        }                    } // it's SO UGLY!                }            }        }                return 0;    } </PRE></TD></TR></TABLE><P>Notice I have two file descriptor sets in the code:<TTCLASS="parameter"><I>master</I></TT> and <TTCLASS="parameter"><I>read_fds</I></TT>.  Thefirst, <TTCLASS="parameter"><I>master</I></TT>, holds all the socket descriptorsthat are currently connected, as well as the socket descriptor that islistening for new connections.</P><P>The reason I have the <TTCLASS="parameter"><I>master</I></TT> set is that<TTCLASS="function">select()</TT> actually <EM>changes</EM> theset you pass into it to reflect which sockets are ready to read.  SinceI have to keep track of the connections from one call of<TTCLASS="function">select()</TT> to the next, I must store these safelyaway somewhere.  At the last minute, I copy the<TTCLASS="parameter"><I>master</I></TT> into the <TTCLASS="parameter"><I>read_fds</I></TT>,and then call <TTCLASS="function">select()</TT>.</P><P>But doesn't this mean that every time I get a new connection, Ihave to add it to the <TTCLASS="parameter"><I>master</I></TT> set?  Yup!  Andevery time a connection closes, I have to remove it from the<TTCLASS="parameter"><I>master</I></TT> set?  Yes, it does.</P><P>Notice I check to see when the <TTCLASS="parameter"><I>listener</I></TT>socket is ready to read.  When it is, it means I have a new connectionpending, and I <TTCLASS="function">accept()</TT> it and add it to the<TTCLASS="parameter"><I>master</I></TT> set.  Similarly, when a client connectionis ready to read, and <TTCLASS="function">recv()</TT> returns<TTCLASS="constant">0</TT>, I know the client has closed the connection, andI must remove it from the <TTCLASS="parameter"><I>master</I></TT> set.</P><P>If the client <TTCLASS="function">recv()</TT> returns non-zero,though, I know some data has been received.  So I get it, and then gothrough the <TTCLASS="parameter"><I>master</I></TT> list and send that data to allthe rest of the connected clients.</P><P>And that, my friends, is a less-than-simple overview of thealmighty <TTCLASS="function">select()</TT> function.</P></DIV><DIVCLASS="sect2"><H2CLASS="sect2"><ANAME="sendall">6.3. Handling Partial <TTCLASS="function">send()</TT>s</A></H2><P>Remember back in the <AHREF="syscalls.html#sendrecv">section about<TTCLASS="function">send()</TT></A>, above, when I said that<TTCLASS="function">send()</TT> might not send all the bytes you asked itto?  That is, you want it to send 512 bytes, but it returns 412.  Whathappened to the remaining 100 bytes?</P><P>Well, they're still in your little buffer waiting to be sent out.Due to circumstances beyond your control, the kernel decided not to sendall the data out in one chunk, and now, my friend, it's up to you to getthe data out there.</P><P>You could write a function like this to do it, too:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="programlisting">&#13;    #include &#60;sys/types.h&#62;    #include &#60;sys/socket.h&#62;    int sendall(int s, char *buf, int *len)    {        int total = 0;        // how many bytes we've sent        int bytesleft = *len; // how many we have left to send        int n;        while(total &#60; *len) {            n = send(s, buf+total, bytesleft, 0);            if (n == -1) { break; }            total += n;            bytesleft -= n;        }        *len = total; // return number actually sent here        return n==-1?-1:0; // return -1 on failure, 0 on success    } </PRE></TD></TR></TABLE><P>In this example, <TTCLASS="parameter"><I>s</I></TT> is the socket you wantto send the data to, <TTCLASS="parameter"><I>buf</I></TT> is the buffer containingthe data, and <TTCLASS="parameter"><I>len</I></TT> is a pointer to an<TTCLASS="type">int</TT> containing the number of bytes in the buffer.</P><P>The function returns <TTCLASS="constant">-1</TT> on error (and<TTCLASS="parameter"><I>errno</I></TT> is still set from the call to<TTCLASS="function">send()</TT>.)  Also, the number of bytes actually sentis returned in <TTCLASS="parameter"><I>len</I></TT>.  This will be the same numberof bytes you asked it to send, unless there was an error.<TTCLASS="function">sendall()</TT> will do it's best, huffing and puffing,to send the data out, but if there's an error, it gets back to you rightaway.</P><P>For completeness, here's a sample call to the function:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="programlisting">&#13;    char buf[10] = "Beej!";    int len;    len = strlen(buf);    if (sendall(s, buf, &#38;len) == -1) {        perror("sendall");        printf("We only sent %d bytes because of the error!\n", len);    } </PRE></TD></TR></TABLE><P>What happens on the receiver's end when part of a packet arrives?If the packets are variable length, how does the receiver know when onepacket ends and another begins?  Yes, real-world scenarios are a royalpain in the donkeys.  You probably have to<EM>encapsulate</EM> (remember that from the <AHREF="theory.html#lowlevel">data encapsulation section</A> way back there atthe beginning?)  Read on for details!</P></DIV><DIVCLASS="sect2"><H2CLASS="sect2"><ANAME="sonofdataencap">6.4. Son of Data Encapsulation</A></H2><P>What does it really mean to encapsulate data, anyway?  In thesimplest case, it means you'll stick a header on there with either someidentifying information or a packet length, or both.</P><P>What should your header look like?  Well, it's just some binarydata that represents whatever you feel is necessary to complete yourproject.</P><P>Wow.  That's vague.</P><P>Okay.  For instance, let's say you have a multi-user chat programthat uses <TTCLASS="constant">SOCK_STREAM</TT>s.  When a user types ("says")something, two pieces of information need to be transmitted to theserver: what was said and who said it.</P><P>So far so good?  "What's the problem?" you're asking.</P><P>The problem is that the messages can be of varying lengths.  Oneperson named "tom" might say, "Hi", and another person named"Benjamin" might say, "Hey guys what is up?"</P><P>So you <TTCLASS="function">send()</TT> all this stuff to the clientsas it comes in.  Your outgoing data stream looks like this:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="screen">&#13;    t o m H i B e n j a m i n H e y g u y s w h a t i s u p ?</PRE></TD></TR></TABLE><P>And so on.  How does the client know when one message starts andanother stops?  You could, if you wanted, make all messages the samelength and just call the <TTCLASS="function">sendall()</TT> we implemented,<AHREF="advanced.html#sendall">above</A>.  But that wastes bandwidth!  Wedon't want to <TTCLASS="function">send()</TT> 1024 bytes just so "tom" cansay "Hi".</P><P>So we <EM>encapsulate</EM> the data in a tiny headerand packet structure.  Both the client and server know how to pack andunpack (sometimes referred to as "marshal" and "unmarshal") this data.Don't look now, but we're starting to define a<EM>protocol</EM> that describes how a client and servercommunicate!</P><P>In this case, let's assume the user name is a fixed length of 8characters, padded with <TTCLASS="constant">'\0'</TT>.  And then let'sassume the data is variable length, up to a maximum of 128characters.  Let's have a look a sample packet structure that we mightuse in this situation:</P><P></P><OLTYPE="1"><LI><P><TTCLASS="computeroutput">len</TT> (1 byte, unsigned)-- The total length of the packet, counting the 8-byte user name andchat data.</P></LI><LI><P><TTCLASS="computeroutput">name</TT> (8 bytes) -- Theuser's name, NUL-padded if necessary.</P></LI><LI><P><TTCLASS="computeroutput">chatdata</TT>(<EM>n</EM>-bytes) -- The data itself, no more than 128bytes.  The length of the packet should be calculated as the length ofthis data plus 8 (the length of the name field,above).</P></LI></OL><P>Why did I choose the 8-byte and 128-byte limits for the fields?  Ipulled them out of the air, assuming they'd be long enough.  Maybe,though, 8 bytes is too restrictive for your needs, and you can have a30-byte name field, or whatever.  The choice is up to you.</P><P>Using the above packet definition, the first packet would consistof the following information (in hex and ASCII):</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="screen">&#13;      0A     74 6F 6D 00 00 00 00 00      48 69   (length)  T  o  m    (padding)         H  i</PRE></TD></TR></TABLE><P>And the second is similar:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="screen">&#13;      14     42 65 6E 6A 61 6D 69 6E      48 65 79 20 67 75 79 73 20 77 ...   (length)  B  e  n  j  a  m  i  n       H  e  y     g  u  y  s     w  ...</PRE></TD></TR></TABLE><P>(The length is stored in Network Byte Order, of course.  In thiscase, it's only one byte so it doesn't matter, but generally speakingyou'll want all your binary integers to be stored in Network Byte Orderin your packets.)</P><P>When you're sending this data, you should be safe and use acommand similar to <AHREF="advanced.html#sendall"><TTCLASS="function">sendall()</TT></A>, above, so youknow all the data is sent, even if it takes multiple calls to<TTCLASS="function">send()</TT> to get it all out.</P><P>Likewise, when you're receiving this data, you need to do a bit of extrawork.  To be safe, you should assume that you might receive a partialpacket (like maybe we receive "<TTCLASS="computeroutput">00 14 42 656E</TT>" from Benjamin, above, but that's all we get in thiscall to <TTCLASS="function">recv()</TT>).  We need to call<TTCLASS="function">recv()</TT> over and over again until the packet iscompletely received.</P><P>But how?  Well, we know the number of bytes we need to receive intotal for the packet to be complete, since that number is tacked on thefront of the packet.  We also know the maximum packet size is 1+8+128,or 137 bytes (because that's how we defined the packet.)</P><P>What you can do is declare an array big enough for two packets.This is your work array where you will reconstruct packets as theyarrive.</P><P>Every time you <TTCLASS="function">recv()</TT> data, you'll feed itinto the work buffer and check to see if the packet is complete.  Thatis, the number of bytes in the buffer is greater than or equal to thelength specified in the header (+1, because the length in the headerdoesn't include the byte for the length itself.)  If the number of bytesin the buffer is less than 1, the packet is not complete, obviously.You have to make a special case for this, though, since the first byteis garbage and you can't rely on it for the correct packetlength.</P><P>Once the packet is complete, you can do with it what youwill.  Use it, and remove it from your work buffer.</P><P>Whew!  Are you juggling that in your head yet?  Well, here's thesecond of the one-two punch: you might have read past the end of onepacket and onto the next in a single <TTCLASS="function">recv()</TT> call.That is, you have a work buffer with one complete packet, and anincomplete part of the next packet!  Bloody heck.  (But this is why youmade your work buffer large enough to hold <EM>two</EM>packets--in case this happened!)</P><P>Since you know the length of the first packet from the header, andyou've been keeping track of the number of bytes in the work buffer, youcan subtract and calculate how many of the bytes in the work bufferbelong to the second (incomplete) packet.  When you've handled the firstone, you can clear it out of the work buffer and move the partial secondpacked down the to front of the buffer so it's all ready to go for thenext <TTCLASS="function">recv()</TT>.</P><P>(Some of you readers will note that actually moving the partialsecond packet to the beginning of the work buffer takes time, and theprogram can be coded to not require this by using a circular buffer.Unfortunately for the rest of you, a discussion on circular buffers isbeyond the scope of this article.  If you're still curious, grab a datastructures book and go from there.)</P><P>I never said it was easy.  Ok, I did say it was easy.  And it is;you just need practice and pretty soon it'll come to you naturally.  ByExcalibur I swear it!</P></DIV></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="clientserver.html">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="reference.html">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Client-Server Background</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top">&nbsp;</TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">More References</TD></TR></TABLE></DIV></BODY></HTML>

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
久久伊99综合婷婷久久伊| 日韩精品亚洲专区| 蜜臀av一区二区三区| 国产凹凸在线观看一区二区| 欧美日韩在线观看一区二区| 中文字幕免费不卡| 男人的j进女人的j一区| 日本道色综合久久| 国产精品伦理在线| 九九精品视频在线看| 欧美日韩国产免费| 亚洲欧美偷拍另类a∨色屁股| 国产尤物一区二区在线| 欧美一级免费大片| 亚洲mv在线观看| 色菇凉天天综合网| 亚洲色图视频免费播放| 国产成人免费在线| 久久久国产精华| 精品亚洲免费视频| 日韩欧美一级片| 日韩国产一区二| 欧美日本高清视频在线观看| 亚洲精品乱码久久久久久 | 亚洲国产精品成人综合色在线婷婷| 午夜免费久久看| 欧美日韩成人激情| 日韩av一区二区三区四区| 91麻豆精品久久久久蜜臀| 五月激情综合婷婷| 91精品国产91热久久久做人人 | 1024成人网色www| 成人黄色综合网站| 国产精品久久久久久亚洲伦| 粉嫩aⅴ一区二区三区四区| 国产欧美日韩综合精品一区二区| 国产一区不卡视频| 国产女人水真多18毛片18精品视频| 国产乱码精品一区二区三区忘忧草| 久久尤物电影视频在线观看| 国产精品夜夜嗨| 国产精品久久精品日日| 色妹子一区二区| 午夜久久久久久久久久一区二区| 911精品国产一区二区在线| 久久成人羞羞网站| 国产女主播在线一区二区| 成人激情综合网站| 亚洲一二三四区不卡| 51精品国自产在线| 国产综合久久久久影院| 国产精品天干天干在观线| 91亚洲午夜精品久久久久久| 亚洲大片在线观看| 日韩精品一区二区三区视频播放 | 欧美经典一区二区| 91麻豆国产福利精品| 亚洲成人动漫一区| 精品理论电影在线观看| av动漫一区二区| 午夜电影久久久| 久久精品亚洲精品国产欧美 | 亚洲美女精品一区| 在线成人av影院| 丁香婷婷综合色啪| 丝袜美腿亚洲一区二区图片| 欧美精品一区二区三区一线天视频| 国产大陆a不卡| 亚洲国产精品久久久久婷婷884| 欧美成人性战久久| 91视频com| 国产一区二区免费在线| 一区二区三区久久| 精品福利一二区| 欧美性受xxxx黑人xyx性爽| 精品亚洲成a人| 亚洲一区二区三区三| 国产欧美日韩麻豆91| 欧美一区二区三区在线看| 成人黄色综合网站| 久久99在线观看| 亚洲第一搞黄网站| 中文字幕佐山爱一区二区免费| 日韩免费高清电影| 欧美日韩综合不卡| 成人av一区二区三区| 美女在线视频一区| 亚洲成人精品一区二区| 亚洲图片另类小说| 久久久久久久久久久久久女国产乱| 欧美天堂亚洲电影院在线播放 | 国产乱码精品一区二区三区忘忧草| 有码一区二区三区| 亚洲国产精品v| 精品国产sm最大网站免费看| 欧美日韩中文国产| 91热门视频在线观看| 国产精品自拍av| 精品一区二区在线观看| 美女精品自拍一二三四| 视频在线在亚洲| 亚洲一区二区三区爽爽爽爽爽| 国产精品理论片在线观看| 久久精品欧美一区二区三区不卡| 91精品免费观看| 欧美日韩精品欧美日韩精品一| 在线日韩一区二区| 91国偷自产一区二区开放时间| 91色视频在线| 91福利精品视频| 欧美午夜不卡在线观看免费| 91久久精品一区二区| 色欧美片视频在线观看在线视频| av电影在线观看完整版一区二区| 成人av在线资源网| 92精品国产成人观看免费| 91日韩在线专区| 在线免费观看日韩欧美| 在线观看日韩精品| 欧美日韩亚洲综合在线| 欧美精品一二三| 欧美一区二视频| 久久综合九色综合欧美亚洲| 国产亚洲精品免费| 亚洲天堂精品视频| 一区二区三区久久| 日本大胆欧美人术艺术动态| 狂野欧美性猛交blacked| 韩日av一区二区| 91在线小视频| 欧美丰满少妇xxxxx高潮对白| 日韩欧美一区在线| 久久精品一二三| 亚洲精品福利视频网站| 日产欧产美韩系列久久99| 久久国产麻豆精品| eeuss鲁片一区二区三区在线观看| 97aⅴ精品视频一二三区| 欧美无砖专区一中文字| xf在线a精品一区二区视频网站| 国产精品美女久久久久久| 一区二区三区电影在线播| 日本欧美久久久久免费播放网| 国产毛片精品一区| 91激情五月电影| 精品99一区二区三区| 亚洲乱码精品一二三四区日韩在线| 亚洲va中文字幕| 精品一区二区三区在线观看国产| 懂色一区二区三区免费观看| 欧美日韩mp4| 国产精品天天看| 免费av网站大全久久| 不卡一二三区首页| 91精品国产福利在线观看| 国产精品乱子久久久久| 麻豆精品一区二区av白丝在线| www.亚洲在线| 日韩精品专区在线影院重磅| 国产精品美女久久久久久久久| 午夜影视日本亚洲欧洲精品| 国产乱一区二区| 91麻豆精品国产无毒不卡在线观看| 亚洲国产成人自拍| 久久成人18免费观看| 欧美无乱码久久久免费午夜一区| 亚洲精品在线观看网站| 香蕉加勒比综合久久| 色综合久久久久网| 欧美国产欧美综合| 奇米亚洲午夜久久精品| 欧美三级日本三级少妇99| 国产精品九色蝌蚪自拍| 国产一区二区三区久久悠悠色av| 欧美日韩精品免费| 一区二区成人在线| eeuss鲁片一区二区三区| 久久久国际精品| 经典三级视频一区| 欧美一区二区三区免费视频| 亚洲第一狼人社区| 欧美在线视频不卡| 亚洲精品第1页| 91色视频在线| 亚洲人吸女人奶水| www.性欧美| 中文字幕不卡在线播放| 国产传媒一区在线| 久久久久久久久久久久久女国产乱 | 日韩高清中文字幕一区| 欧美午夜寂寞影院| 一区二区三区中文免费| 91丨porny丨国产| 一区二区三区美女| 欧美少妇bbb| 天堂av在线一区| 精品欧美一区二区久久| 精品一区二区三区在线播放 | 成人免费在线视频观看| 国产不卡视频一区二区三区|