⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 faq.html

📁 Beej的socket教材
💻 HTML
📖 第 1 页 / 共 2 页
字号:
><B>Q: </B>How can I implement a timeout on a call to<TTCLASS="function">recv()</TT>?</P></DIV><DIVCLASS="answer"><P><B>A: </B>Use <AHREF="advanced.html#select"><TTCLASS="function">select()</TT></A>!  It allows you tospecify a timeout parameter for socket descriptors that you're lookingto read from.  Or, you could wrap the entire functionality in a singlefunction, like this:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="programlisting">&#13;#include &#60;unistd.h&#62;#include &#60;sys/time.h&#62;#include &#60;sys/types.h&#62;#include &#60;sys/socket.h&#62;int recvtimeout(int s, char *buf, int len, int timeout){    fd_set fds;    int n;    struct timeval tv;    // set up the file descriptor set    FD_ZERO(&#38;fds);    FD_SET(s, &#38;fds);    // set up the struct timeval for the timeout    tv.tv_sec = timeout;    tv.tv_usec = 0;    // wait until timeout or data received    n = select(s+1, &#38;fds, NULL, NULL, &#38;tv);    if (n == 0) return -2; // timeout!    if (n == -1) return -1; // error    // data must be here, so do a normal recv()    return recv(s, buf, len, 0);}// Sample call to recvtimeout():    .    .    n = recvtimeout(s, buf, sizeof(buf), 10); // 10 second timeout    if (n == -1) {        // error occurred        perror("recvtimeout");    }    else if (n == -2) {        // timeout occurred    } else {        // got some data in buf    }    .    . </PRE></TD></TR></TABLE><P>Notice that <TTCLASS="function">recvtimeout()</TT> returns<TTCLASS="constant">-2</TT> in case of a timeout.  Why not return<TTCLASS="constant">0</TT>?  Well, if you recall, a return value of<TTCLASS="constant">0</TT> on a call to <TTCLASS="function">recv()</TT> meansthat the remote side closed the connection.  So that return value isalready spoken for, and <TTCLASS="constant">-1</TT> means "error", so Ichose <TTCLASS="constant">-2</TT> as my timeout indicator.</P></DIV></DIV><DIVCLASS="qandaentry"><DIVCLASS="question"><P><ANAME="AEN1461"></A><B>Q: </B>How do I encrypt or compress the data before sending itthrough the socket?</P></DIV><DIVCLASS="answer"><P><B>A: </B>One easy way to do encryption is to use SSL (secure socketslayer), but that's beyond the scope of this guide.</P><P>But assuming you want to plug in or implement your own compressoror encryption system, it's just a matter of thinking of your data asrunning through a sequence of steps between both ends.  Each stepchanges the data in some way.</P><P>&#13;<P></P><OLTYPE="1"><LI><P>server reads data from file (or whereever)</P></LI><LI><P>server encrypts data  (you add this part)</P></LI><LI><P>server <TTCLASS="function">send()</TT>s encrypted data</P></LI></OL></P><P>Now the other way around:</P><P>&#13;<P></P><OLSTART="4"TYPE="1"><LI><P>client <TTCLASS="function">recv()</TT>s encrypted data</P></LI><LI><P>client decrypts data  (you add this part)</P></LI><LI><P>client writes data to file (or whereever)</P></LI></OL></P><P>You can also do compression at the same point that you do theencryption/decryption, above.  Or you could do both!  Just remember tocompress before you encrypt.  <TTCLASS="computeroutput">:)</TT></P><P>Just as long as the client properly undoes what the server does,the data will be fine in the end no matter how many intermediate stepsyou add.</P><P>So all you need to do to use my code is to find the place betweenwhere the data is read and the data is sent (using<TTCLASS="function">send()</TT>) over the network, and stick some code inthere that does the encryption.</P></DIV></DIV><DIVCLASS="qandaentry"><DIVCLASS="question"><P><ANAME="AEN1491"></A><B>Q: </B>What is this "<TTCLASS="constant">PF_INET</TT>" I keepseeing?  Is it related to<TTCLASS="constant">AF_INET</TT>?</P></DIV><DIVCLASS="answer"><P><B>A: </B>Yes, yes it is.  See <AHREF="syscalls.html#socket">the section on<TTCLASS="function">socket()</TT></A> for details.</P></DIV></DIV><DIVCLASS="qandaentry"><DIVCLASS="question"><P><ANAME="AEN1500"></A><B>Q: </B>How can I write a server that accepts shell commandsfrom a client and executes them?</P></DIV><DIVCLASS="answer"><P><B>A: </B>For simplicity, lets say the client<TTCLASS="function">connect()</TT>s, <TTCLASS="function">send()</TT>s, and<TTCLASS="function">close()</TT>s the connection (that is, there are nosubsequent system calls without the client connecting again.)</P><P>The process the client follows is this:</P><P>&#13;<P></P><OLTYPE="1"><LI><P><TTCLASS="function">connect()</TT> to server</P></LI><LI><P><TTCLASS="function">send("/sbin/ls &#62; /tmp/client.out")</TT></P></LI><LI><P><TTCLASS="function">close()</TT> the connection</P></LI></OL></P><P>Meanwhile, the server is handling the data and executingit:</P><P>&#13;<P></P><OLTYPE="1"><LI><P><TTCLASS="function">accept()</TT> the connection from the client</P></LI><LI><P><TTCLASS="function">recv(str)</TT> the command string</P></LI><LI><P><TTCLASS="function">close()</TT> the connection</P></LI><LI><P><TTCLASS="function">system(str)</TT> to run the command</P></LI></OL></P><P><EM>Beware!</EM>  Having the server execute what theclient says is like giving remote shell access and people can do thingsto your account when they connect to the server.  For instance, in theabove example, what if the client sends "<BCLASS="command">rm -rf ~</B>"?It deletes everything in your account, that's what!</P><P>So you get wise, and you prevent the client from using any exceptfor a couple utilities that you know are safe, like the<BCLASS="command">foobar</B> utility:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="programlisting">&#13;    if (!strcmp(str, "foobar")) {        sprintf(sysstr, "%s &#62; /tmp/server.out", str);        system(sysstr);    } </PRE></TD></TR></TABLE><P>But you're still unsafe, unfortunately: what if the client enters"<BCLASS="command">foobar; rm -rf ~</B>"?  The safest thing to do is towrite a little routine that puts an escape ("<TTCLASS="constant">\</TT>")character in front of all non-alphanumeric characters (including spaces,if appropriate) in the arguments for the command.</P><P>As you can see, security is a pretty big issue when the serverstarts executing things the client sends.</P></DIV></DIV><DIVCLASS="qandaentry"><DIVCLASS="question"><P><ANAME="AEN1545"></A><B>Q: </B>I'm sending a slew of data, but when I<TTCLASS="function">recv()</TT>, it only receives 536 bytes or 1460 bytes ata time.  But if I run it on my local machine, it receives all the dataat the same time.  What's going on?</P></DIV><DIVCLASS="answer"><P><B>A: </B>You're hitting the MTU--the maximum size the physical medium canhandle.  On the local machine, you're using the loopback device whichcan handle 8K or more no problem.  But on ethernet, which can onlyhandle 1500 bytes with a header, you hit that limit.  Over a modem, with576 MTU (again, with header), you hit the even lower limit.</P><P>You have to make sure all the data is being sent, first of all.(See the <AHREF="advanced.html#sendall"><TTCLASS="function">sendall()</TT></A>function implementation for details.) Once you're sure of that, then youneed to call <TTCLASS="function">recv()</TT> in a loop until all your datais read.</P><P>Read the section <AHREF="advanced.html#sonofdataencap">Son of DataEncapsulation</A> for details on receiving complete packets of datausing multiple calls to <TTCLASS="function">recv()</TT>.</P></DIV></DIV><DIVCLASS="qandaentry"><DIVCLASS="question"><P><ANAME="AEN1558"></A><B>Q: </B>I'm on a Windows box and I don't have the<TTCLASS="function">fork()</TT> system call or any kind of <TTCLASS="type">structsigaction</TT>.  What to do?</P></DIV><DIVCLASS="answer"><P><B>A: </B>If they're anywhere, they'll be in POSIX libraries that may haveshipped with your compiler.  Since I don't have a Windows box, I reallycan't tell you the answer, but I seem to remember that Microsoft has aPOSIX compatibility layer and that's where <TTCLASS="function">fork()</TT>would be.  (And maybe even <TTCLASS="type">sigaction</TT>.)</P><P>Search the help that came with VC++ for "fork" or "POSIX" and see if itgives you any clues.</P><P>If that doesn't work at all, ditch the<TTCLASS="function">fork()</TT>/<TTCLASS="type">sigaction</TT> stuff and replace itwith the Win32 equivalent: <TTCLASS="function">CreateProcess()</TT>.  Idon't know how to use <TTCLASS="function">CreateProcess()</TT>--it takes abazillion arguments, but it should be covered in the docs that came withVC++.</P></DIV></DIV><DIVCLASS="qandaentry"><DIVCLASS="question"><P><ANAME="AEN1573"></A><B>Q: </B>How do I send data securely with TCP/IP usingencryption?</P></DIV><DIVCLASS="answer"><P><B>A: </B>Check out the <AHREF="http://www.openssl.org/"TARGET="_top">OpenSSLproject</A>.</P></DIV></DIV><DIVCLASS="qandaentry"><DIVCLASS="question"><P><ANAME="AEN1579"></A><B>Q: </B>I'm behind a firewall--how do I let people outside thefirewall know my IP address so they can connect to mymachine?</P></DIV><DIVCLASS="answer"><P><B>A: </B>Unfortunately, the purpose of a firewall is to preventpeople outside the firewall from connecting to machines inside thefirewall, so allowing them to do so is basically considered a breach ofsecurity.</P><P>This isn't to say that all is lost.  For one thing, you can stilloften <TTCLASS="function">connect()</TT> through the firewall if it's doingsome kind of masquerading or NAT or something like that.  Just designyour programs so that you're always the one initiating the connection,and you'll be fine.</P><P>If that's not satisfactory, you can ask your sysadmins to poke ahole in the firewall so that people can connect to you.  The firewallcan forward to you either through it's NAT software, or through a proxyor something like that.</P><P>Be aware that a hole in the firewall is nothing to be takenlightly.  You have to make sure you don't give bad people access to theinternal network; if you're a beginner, it's a lot harder to makesoftware secure than you might imagine.</P><P>Don't make your sysadmin mad at me.<TTCLASS="computeroutput">;-)</TT></P></DIV></DIV></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="reference.html">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="conclusion.html">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">More References</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top">&nbsp;</TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Disclaimer and Call for Help</TD></TR></TABLE></DIV></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -