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

📄 server

📁 一个linux网络开发的示例
💻
📖 第 1 页 / 共 5 页
字号:
function anonymous()
{
 img_auto_size(this,450,true);
}
}
}" align="baseline" /></p><p>下面是一个演示IO多路复用的源程序,是一个端口转发程序,但它的用处相当大,实际应用中的各类代理软件或端口映射软件都是基于这样的代码的,比如Windows下的WinGate、WinProxy等都是在此基础上实现的。源代码如下:<br /><table style="WIDTH: 100%" cellspacing="1" cellpadding="1" align="baseline" border="1"><tbody><tr><td><p>/*----------------------源代码开始--------------------------------------------*/<br />#include &lt;stdlib.h&gt;<br />#include &lt;stdio.h&gt;<br />#include &lt;unistd.h&gt;<br />#include &lt;sys/time.h&gt;<br />#include &lt;sys/types.h&gt;<br />#include &lt;string.h&gt;<br />#include &lt;signal.h&gt;<br />#include &lt;sys/socket.h&gt;<br />#include &lt;netinet/in.h&gt;<br />#include &lt;arpa/inet.h&gt;<br />#include &lt;errno.h&gt;<br /></p><p>static int forward_port;</p><p>#undef max<br />#define max(x,y) ((x) &gt; (y) ? (x) : (y))</p><p>/*************************关于本文档************************************<br />*filename: tcpforwardport.c<br />*purpose: 演示了select的用法,这是一个极好的代理软件核心,专门作端口映射用<br />*tidied by: zhoulifa(<a href="mailto:zhoulifa@163.com">zhoulifa@163.com</a>) 周立发(<a href="http://zhoulifa.bokee.com/">http://zhoulifa.bokee.com</a>)<br />Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言<br />*date time:2006-07-05 19:00:00<br />*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途<br />* 但请遵循GPL<br />*Thanks to: Paul Sheer 感谢Paul Sheer在select_tut的man手册里提供了这份源代码<br />*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力<br />*********************************************************************/</p><p>static int listen_socket (int listen_port) {<br />&nbsp;&nbsp;&nbsp; struct sockaddr_in a;<br />&nbsp;&nbsp;&nbsp; int s;<br />&nbsp;&nbsp;&nbsp; int yes;<br />&nbsp;&nbsp;&nbsp; if ((s = socket (AF_INET, SOCK_STREAM, 0)) &lt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perror (&quot;socket&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; yes = 1;<br />&nbsp;&nbsp;&nbsp; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &amp;yes, sizeof (yes)) &lt;<br />0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perror (&quot;setsockopt&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close (s);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; memset (&amp;a, 0, sizeof (a));<br />&nbsp;&nbsp;&nbsp; a.sin_port = htons (listen_port);<br />&nbsp;&nbsp;&nbsp; a.sin_family = AF_INET;<br />&nbsp;&nbsp;&nbsp; if (bind(s, (struct sockaddr *) &amp;a, sizeof (a)) &lt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perror (&quot;bind&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close (s);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; printf (&quot;accepting connections on port %d\n&quot;, (int) listen_port);<br />&nbsp;&nbsp;&nbsp; listen (s, 10);<br />&nbsp;&nbsp;&nbsp; return s;<br />}</p><p>static int connect_socket (int connect_port, char *address) {<br />&nbsp;&nbsp;&nbsp; struct sockaddr_in a;<br />&nbsp;&nbsp;&nbsp; int s;<br />&nbsp;&nbsp;&nbsp; if ((s = socket (AF_INET, SOCK_STREAM, 0)) &lt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perror (&quot;socket&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close (s);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br />&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp; memset (&amp;a, 0, sizeof (a));<br />&nbsp;&nbsp;&nbsp; a.sin_port = htons (connect_port);<br />&nbsp;&nbsp;&nbsp; a.sin_family = AF_INET;</p><p>&nbsp;&nbsp;&nbsp; if (!inet_aton(address, (struct in_addr *) &amp;a.sin_addr.s_addr)) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perror (&quot;bad IP address format&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close (s);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br />&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp; if (connect(s, (struct sockaddr *) &amp;a, sizeof (a)) &lt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perror (&quot;connect()&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shutdown (s, SHUT_RDWR);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close (s);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; return s;<br />}</p><p>#define SHUT_FD1 { \<br />&nbsp;&nbsp;&nbsp; if (fd1 &gt;= 0) {&nbsp;&nbsp; \<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shutdown (fd1, SHUT_RDWR);&nbsp; \<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close (fd1);&nbsp; \<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fd1 = -1;&nbsp;&nbsp;&nbsp;&nbsp; \<br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; \<br />}</p><p>#define SHUT_FD2 { \<br />&nbsp;&nbsp;&nbsp; if (fd2 &gt;= 0) {&nbsp;&nbsp; \<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shutdown (fd2, SHUT_RDWR);&nbsp; \<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close (fd2);&nbsp; \<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fd2 = -1;&nbsp;&nbsp;&nbsp;&nbsp; \<br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; \<br />}</p><p>#define BUF_SIZE 1024</p><p>int main (int argc, char **argv) {<br />&nbsp;&nbsp;&nbsp; int h;<br />&nbsp;&nbsp;&nbsp; int fd1 = -1, fd2 = -1;<br />&nbsp;&nbsp;&nbsp; char buf1[BUF_SIZE], buf2[BUF_SIZE];<br />&nbsp;&nbsp;&nbsp; int buf1_avail, buf1_written;<br />&nbsp;&nbsp;&nbsp; int buf2_avail, buf2_written;</p><p>&nbsp;&nbsp;&nbsp; if (argc != 4) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf (stderr, &quot;Usage\n\tfwd <listen-port />&nbsp; <forward-to-port /><forward-to-ip-address />\n&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit (1);<br />&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp; signal (SIGPIPE, SIG_IGN);</p><p>&nbsp;&nbsp;&nbsp; forward_port = atoi (argv[2]);</p><p>&nbsp;&nbsp;&nbsp; /*建立监听socket*/<br />&nbsp;&nbsp;&nbsp; h = listen_socket (atoi (argv[1]));<br />&nbsp;&nbsp;&nbsp; if (h &lt; 0)&nbsp;exit (1);</p><p>&nbsp;&nbsp;&nbsp; for (;;) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int r, nfds = 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fd_set rd, wr, er;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_ZERO (&amp;rd);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_ZERO (&amp;wr);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_ZERO (&amp;er);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_SET (h, &amp;rd);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*把监听socket和可读socket三个一起放入select的可读句柄列表里*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nfds = max (nfds, h);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd1 &gt; 0 &amp;&amp; buf1_avail &lt; BUF_SIZE) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_SET (fd1, &amp;rd);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nfds = max (nfds, fd1);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd2 &gt; 0 &amp;&amp; buf2_avail &lt; BUF_SIZE) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_SET (fd2, &amp;rd);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nfds = max (nfds, fd2);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*把可写socket两个一起放入select的可写句柄列表里*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd1 &gt; 0 &amp;&amp; buf2_avail - buf2_written &gt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_SET (fd1, &amp;wr);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nfds = max (nfds, fd1);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd2 &gt; 0 &amp;&amp; buf1_avail - buf1_written &gt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_SET (fd2, &amp;wr);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nfds = max (nfds, fd2);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*把有异常数据的socket两个一起放入select的异常句柄列表里*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd1 &gt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_SET (fd1, &amp;er);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nfds = max (nfds, fd1);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd2 &gt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_SET (fd2, &amp;er);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nfds = max (nfds, fd2);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*开始select*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = select (nfds + 1, &amp;rd, &amp;wr, &amp;er, NULL);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (r == -1 &amp;&amp; errno == EINTR) continue;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (r &lt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perror (&quot;select()&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit (1);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*处理新连接*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (FD_ISSET (h, &amp;rd)) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int l;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct sockaddr_in client_address;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memset (&amp;client_address, 0, l = sizeof (client_address));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = accept (h, (struct sockaddr *)&amp;client_address, &amp;l);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (r &lt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perror (&quot;accept()&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*关闭原有连接,把新连接作为fd1,同时连接新的目标fd2*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SHUT_FD1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SHUT_FD2;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf1_avail = buf1_written = 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf2_avail = buf2_written = 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fd1 = r;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fd2 = connect_socket (forward_port, argv[3]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd2 &lt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SHUT_FD1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf (&quot;connect from %s\n&quot;, inet_ntoa(client_address.sin_addr));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* NB: read oob data before normal reads */<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd1 &gt; 0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (FD_ISSET (fd1, &amp;er)) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char c;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errno = 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = recv (fd1, &amp;c, 1, MSG_OOB);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (r &lt; 1) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SHUT_FD1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; send (fd2, &amp;c, 1, MSG_OOB);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd2 &gt; 0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (FD_ISSET (fd2, &amp;er)) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char c;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errno = 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = recv (fd2, &amp;c, 1, MSG_OOB);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (r &lt; 1) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SHUT_FD1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; send (fd1, &amp;c, 1, MSG_OOB);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* NB: read data from fd1 */<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd1 &gt; 0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (FD_ISSET (fd1, &amp;rd)) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = read (fd1, buf1 + buf1_avail, BUF_SIZE - buf1_avail);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (r &lt; 1) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SHUT_FD1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf1_avail += r;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* NB: read data from fd2 */<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd2 &gt; 0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (FD_ISSET (fd2, &amp;rd)) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = read (fd2, buf2 + buf2_avail, BUF_SIZE - buf2_avail);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (r &lt; 1) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SHUT_FD2;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf2_avail += r;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* NB: write data to fd1 */<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd1 &gt; 0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (FD_ISSET (fd1, &amp;wr)) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = write (fd1, buf2 + buf2_written, buf2_avail - buf2_written);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (r &lt; 1) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SHUT_FD1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf2_written += r;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* NB: write data to fd1 */<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd2 &gt; 0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (FD_ISSET (fd2, &amp;wr)) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = write (fd2, buf1 + buf1_written, buf1_avail - buf1_written);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (r &lt; 1) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SHUT_FD2;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf1_written += r;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* check if write data has caught read data */<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (buf1_written == buf1_avail) buf1_written = buf1_avail = 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (buf2_written == buf2_avail) buf2_written = buf2_avail = 0;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* one side has closed the connection, keep writing to the other side until empty */<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd1 &lt; 0 &amp;&amp; buf1_avail - buf1_written == 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SHUT_FD2;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fd2 &lt; 0 &amp;&amp; buf2_avail - buf2_written == 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SHUT_FD1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; return 0;<br />}<br />/*----------------------源代码结束--------------------------------------------*/<br /></p></td></tr></tbody></table></p>用gcc tcpforwardport.c -o MyProxy编译此程序后运行效果如下:<br /><table style="WIDTH: 100%" cellspacing="1" cellpadding="1" align="baseline" border="1"><tbody><tr><td>./MyProxy 8000 80 172.16.100.218<br />accepting connections on port 8000<br />connect from 127.0.0.1<br /></td></tr></tbody></table><p>当有用户访问本机的8000端口时,MyProxy程序将把此请求转发到172.16.100.218主机的80端口,即实现了一个http代理。</p><p>关于select函数:<br />其函数原型为:<br />int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);<br />此函数的功能是由内核检测在timeout时间内,是否有readfds,writefds,exceptfds三个句柄集(file descriptors)里的某个句柄(file descriptor)的状态符合寻求,即readfds句柄集里有句柄可读或writefds句柄集里有可写或exceptfds句柄集里有例外发生,任何一个有变化函数就立即返回,返回值为timeout发生状态变化的句柄个数。<br />n是所有readfds,writefds,exceptfds三个句柄集(file descriptors)里编号最大值加1。比如:要检测两个socket句柄fd1和fd2在timeout时间内是否分别可读和可写就可以这样:<br />先把两个句柄集(file descriptors)清零:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_ZERO (&amp;readfds);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_ZERO (&amp;writefds);<br />然后把fd1加入读检测集:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_SET (fd1, &amp;readfds);<br />然后把fd2加入写检测集:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_SET (fd2, &amp;writefds);<br />再给timeout设置值,timeout是这样的一个结构:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct timeval {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp; tv_sec;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* seconds */<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp; tv_usec;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* microseconds */<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br />你可以这样赋值:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeout.tv_sec=1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeout.tv_uec=0;<br />表示检测在1秒钟内是否有句柄状态发生变化。<br />如果有句柄发生变化,就可以用FD_ISSET检测各个句柄,比如:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_ISSET (fd1, &amp;readfds);//检测是否fd1变成可读的了<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_ISSET (fd2, &amp;writefds);//检测是否fd2变成可写的了<br />示意程序代码如下:<br /><table style="WIDTH: 100%" cellspacing="1" cellpadding="1" align="baseline" border="1"><tbody><tr><td>/*----------------------示意代码开始--------------------------------------------*/<br />&nbsp;&nbsp;&nbsp; fd1 = socket();//创建一个socket<br />&nbsp;&nbsp;&nbsp; fd2 = socket();//创建一个socket<br />&nbsp;&nbsp;&nbsp; while(1)&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_ZERO (&amp;readfds);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_ZERO (&amp;writefds);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_SET (fd1, &amp;readfds);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_SET (fd2, &amp;writefds);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeout.tv_sec=1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeout.tv_uec=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = select(fd1&gt;fd2?(fd1+1):(fd2+1), &amp;readfds, &amp;writefds, NULL, &amp;timeout);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(ret &lt; 0)&nbsp;{printf(&quot;系统错误,select出错,错误代码:%d, 错误信息:%s&quot;, errno, strerror(errno));}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if(ret == 0)&nbsp;{printf(&quot;select超时返回,没有任何句柄状态发生变化!&quot;);}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //有句柄状态发生了变化<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(FD_ISSET(fd1, &amp;readfds))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fd1有数据可读;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fd1里的数据被读出来;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(FD_ISSET(fd2, &amp;writefds))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fd2可写;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fd2里发送数据给对方;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br />/*----------------------示意代码结束--------------------------------------------*/<br /></td></tr></tbody></table></p>经常用到的几个自定义函数:<br />1、开启监听的函数<br /><table style="WIDTH: 100%" cellspacing="1" cellpadding="1" align="baseline" border="1"><tbody><tr><td><p>/*----------------------源代码代码开始--------------------------------------------*/<br />int<br />OpenSCPServer(int port, int total, int sendbuflen, int recvbuflen, int blockORnot, int reuseORnot)&nbsp;&nbsp;&nbsp; {<br />/*************************关于本函数************************************<br />*function_name: OpenSCPServer<br />*参数说明:port整数型监听端口号,total整数型监听个数,sendbuflen整数型发送缓冲区大小<br />*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; recvbuflen整数型接收缓冲区大小,blockORnot整数型是否阻塞,reuseORnot整数型是否端口重用<br />*purpose: 用来建立一个tcp服务端socket<br />*tidied by: zhoulifa(<a href="mailto:zhoulifa@163.com">zhoulifa@163.com</a>) 周立发(<a href="http://zhoulifa.bokee.com/">http://zhoulifa.bokee.com</a>)<br />Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言<br />*date time:2006-07-05 20:00:00<br />*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途<br />* 但请遵循GPL<br />*Thanks to: Paul Sheer 感谢Paul Sheer在select_tut的man手册里提供了这份源代码<br />*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力<br />*Note:要使用此函数需要自定义一个全局变量char errorMessage[1024];并包含GetCurrentTime.h头文件<br />*********************************************************************/<br />&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp; sockfd = 0, ret = 0, opt = 0, flags=1;<br />&nbsp;&nbsp;&nbsp; struct sockaddr_in&nbsp;&nbsp;&nbsp; laddr;</p><p>&nbsp;&nbsp;&nbsp; ret = sockfd = socket(PF_INET, SOCK_STREAM, 0);<br />&nbsp;&nbsp;&nbsp; if(ret &lt; 0)&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf(errorMessage, &quot;OpenTCPServer socket() error! return:%d, errno=%d, errortext:'%s' %s&quot;, ret, errno, strerror(errno), GetCurrentTime(0, 0));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br />&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp; ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &amp;reuseORnot, sizeof(int));<br />&nbsp;&nbsp;&nbsp; if(ret &lt; 0)&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf(errorMessage, &quot;OpenTCPServer setsockopt() reuse error! return:%d, errno=%d, errortext:'%s' %s&quot;, ret, errno, strerror(errno), GetCurrentTime(0, 0));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -2;<br />&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp; ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &amp;recvbuflen, sizeof(int));<br />&nbsp;&nbsp;&nbsp; if ( ret &lt; 0)&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf(errorMessage, &quot;OpenTCPServer setsockopt() recvbuf error! return:%d, errno=%d, errortext:'%s' %s&quot;, ret, errno, strerror(errno), GetCurrentTime(0, 0));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -3;<br />&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp; ret = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &amp;sendbuflen, sizeof(int));<br />&nbsp;&nbsp;&nbsp; if (ret &lt; 0)&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf(errorMessage, &quot;OpenTCPServer setsockopt() sendbuf error! return:%d, errno=%d, errortext:'%s' %s&quot;, ret, errno, strerror(errno), GetCurrentTime(0, 0));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -4;<br />&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp; ioctl(sockfd,FIONBIO,&amp;blockORnot);/*block or not*/</p><p>&nbsp;&nbsp;&nbsp; laddr.sin_family = PF_INET;<br />&nbsp;&nbsp;&nbsp; laddr.sin_port = htons(port);<br />&nbsp;&nbsp;&nbsp; laddr.sin_addr.s_addr = INADDR_ANY;<br />&nbsp;&nbsp;&nbsp; bzero(&amp;(laddr.sin_zero), 8);</p><p>&nbsp;&nbsp;&nbsp; ret = bind(sockfd, (struct sockaddr *)&amp;laddr, sizeof(struct sockaddr));<br />&nbsp;&nbsp;&nbsp; if(ret &lt; 0)&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf(errorMessage, &quot;OpenTCPServer bind() error! return:%d, errno=%d, errortext:'%s' %s&quot;, ret, errno, strerror(errno), GetCurrentTime(0, 0));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close(sockfd);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -5;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; ret = listen(sockfd, total);<br />&nbsp;&nbsp;&nbsp; if(ret &lt; 0)&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf(errorMessage, &quot;OpenTCPServer listen() error! return:%d, errno=%d, errortext:'%s' %s&quot;, ret, errno, strerror(errno), GetCurrentTime(0, 0));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close(sockfd);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -6;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; sprintf(errorMessage, &quot;OpenTCPServer opened on port.%d(%d) OK, socket(%d), buf(%d:%d)! %s&quot;, port, total, sockfd, sendbuflen, recvbuflen, GetCurrentTime(0, 0));<br />&nbsp;&nbsp;&nbsp; return sockfd;<br />}<br />/*----------------------源代码代码结束--------------------------------------------*/<br /></p></td></tr></tbody></table>2、连接服务器的函数<br /><table style="WIDTH: 100%" cellspac

⌨️ 快捷键说明

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