﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Ah.........FreshMeat.-随笔分类-读书笔记</title><link>http://www.cppblog.com/sixinquan/category/12879.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 22 Feb 2010 09:52:51 GMT</lastBuildDate><pubDate>Mon, 22 Feb 2010 09:52:51 GMT</pubDate><ttl>60</ttl><item><title>UNP读书笔记三 TCP客户/服务器程序分析</title><link>http://www.cppblog.com/sixinquan/archive/2010/02/21/108164.html</link><dc:creator>sin</dc:creator><author>sin</author><pubDate>Sun, 21 Feb 2010 11:49:00 GMT</pubDate><guid>http://www.cppblog.com/sixinquan/archive/2010/02/21/108164.html</guid><wfw:comment>http://www.cppblog.com/sixinquan/comments/108164.html</wfw:comment><comments>http://www.cppblog.com/sixinquan/archive/2010/02/21/108164.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/sixinquan/comments/commentRss/108164.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sixinquan/services/trackbacks/108164.html</trackback:ping><description><![CDATA[首先是一个TCP客户/服务器编程的例子<br><br>客户端<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">unp.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;cli_echo(FILE</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;fp,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;fd);<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argc,&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">**</span><span style="color: #000000;">argv)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;sockfd;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">struct</span><span style="color: #000000;">&nbsp;sockaddr_in&nbsp;servaddr;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(argc&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_quit(</span><span style="color: #000000;">"</span><span style="color: #000000;">usage:echotcp&nbsp;&lt;IPADDRESS&gt;</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;sockfd&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Socket(AF_INET,&nbsp;SOCK_STREAM,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;bzero(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">servaddr,&nbsp;</span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(servaddr));<br>&nbsp;&nbsp;&nbsp;&nbsp;servaddr.sin_family&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;AF_INET;<br>&nbsp;&nbsp;&nbsp;&nbsp;servaddr.sin_port&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;htons(SERV_PORT);<br>&nbsp;&nbsp;&nbsp;&nbsp;Inet_pton(AF_INET,&nbsp;argv[</span><span style="color: #000000;">1</span><span style="color: #000000;">],&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">servaddr.sin_addr);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;Connect(sockfd,&nbsp;(SA</span><span style="color: #000000;">*</span><span style="color: #000000;">)</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">servaddr,&nbsp;</span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(servaddr));<br><br>&nbsp;&nbsp;&nbsp;&nbsp;cli_echo(stdin,&nbsp;sockfd);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br>}<br><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;cli_echo(FILE</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;fp,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;fd)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;nread;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;sendline[MAXLINE],recvline[MAXLINE];<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(&nbsp;Fgets(sendline,MAXLINE,fp)&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;NULL&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Writen(fd,sendline,strlen(sendline));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(&nbsp;Readline(fd,recvline,MAXLINE)</span><span style="color: #000000;">==</span><span style="color: #000000;">0</span><span style="color: #000000;">&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_quit(</span><span style="color: #000000;">"</span><span style="color: #000000;">error:server&nbsp;terminated!</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Fputs(recvline,stdout);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
<br>服务器端<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">unp.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;serv_echo(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;clifd);<br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;sig_child(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;signo);<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argc,&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">**</span><span style="color: #000000;">argv)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;listenfd,clifd;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">struct</span><span style="color: #000000;">&nbsp;sockaddr_in&nbsp;cliaddr,servaddr;<br>&nbsp;&nbsp;&nbsp;&nbsp;socklen_t&nbsp;clilen;<br>&nbsp;&nbsp;&nbsp;&nbsp;pid_t&nbsp;childpid;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;listenfd&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Socket(AF_INET,&nbsp;SOCK_STREAM,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;bzero(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">servaddr,&nbsp;</span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(servaddr));<br>&nbsp;&nbsp;&nbsp;&nbsp;servaddr.sin_family&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;AF_INET;<br>&nbsp;&nbsp;&nbsp;&nbsp;servaddr.sin_addr.s_addr&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;htonl(INADDR_ANY);<br>&nbsp;&nbsp;&nbsp;&nbsp;servaddr.sin_port&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;htons(SERV_PORT);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;Bind(listenfd,&nbsp;(SA</span><span style="color: #000000;">*</span><span style="color: #000000;">)</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">servaddr,&nbsp;</span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(servaddr));<br>&nbsp;&nbsp;&nbsp;&nbsp;Listen(listenfd,&nbsp;LISTENQ);<br>&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGCHLD,sig_child);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(;;)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clilen&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(cliaddr);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;((clifd&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Accept(listenfd,(SA</span><span style="color: #000000;">*</span><span style="color: #000000;">)</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">cliaddr,</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">clilen))&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(errno&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;EINTR)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_sys(</span><span style="color: #000000;">"</span><span style="color: #000000;">accept&nbsp;error</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(&nbsp;(childpid</span><span style="color: #000000;">=</span><span style="color: #000000;">fork())&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Close(listenfd);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">child&nbsp;process&nbsp;%d\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;getpid());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;serv_echo(clifd);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Close(clifd);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br>}<br><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;serv_echo(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;clifd)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;nread;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;recvline[MAXLINE];<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(&nbsp;(nread</span><span style="color: #000000;">=</span><span style="color: #000000;">Readline(clifd,recvline,MAXLINE))&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Writen(clifd,recvline,nread);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;sig_child(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;signo)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;pid_t&nbsp;pid;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;&nbsp;stat;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;pid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;wait(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">stat);<br>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">child&nbsp;%d&nbsp;ternminated\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;pid);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br>}</span></div>
<br><br>正常启动<br>首先服务器程序启动后，调用socket bind listen 和accept，并阻塞在accept。可以用netstat来检测到服务器进程有一个处于LISTEN状态的套接口。然后启动客户程序，客户调用socket connect后，引起TCP的三路握手过程。三路握手完成后，客户程序从connect返回，服务器程序从accept返回，到此TCP连接建立。服务器进程产生一个子进程用来处理于客户的连接，服务器主进程则继续阻塞于accept调用，等待下一个客户连接。<br>连接建立后，客户程序阻塞于fgets调用，等待用户输到此TCP连接建立。入一行。服务器程序则阻塞于readline调用，等待客户程序送出一行。此时可以通过netstat来检测到:服务器主进程处于LISTEN状态，服务器子进程和客户进程则处于ESTABLISHED状态。<br><br>正常终止<br>当对客户程序键入EOL字符(Ctrl+C键)以终止客户，立即运行netstat。可以检测到客户程序的套接口处于TIME_WAIT状态，服务器程序一个套接口则处于LISTEN状态。<br>正常终止过程如下:客户程序接受到终止字符后，从fgets返回一个空指针,客户进程调用exit后结束。于是，客户套接口被内核关闭，并向服务器发送一个FIN，服务器则以ACK相应，此时客户套接口处于FIN_WAIT_2状态，服务器套接口处于CLOSE_WAIT状态。<br>服务器收到FIN时，从readline调用返回并返回0，这导致服务器子进程结束。服务器的连接套接口随之被关闭，服务器子进程向客户发送一个FIN，客户则以ACK回应之，连接终止。客户进程虽然结束，但是客户进程套接口仍然处于TIME_WAIT状态。<br><br>Posix信号<br>信号是发生某事件时对进程的通知，也称为为软中断。可以由一个进程发往另一个进程，也可以由内核发往进程。SIGCHLD信号就是进程终止时，内核发送给终止进程父进程的信号。每个信号都有一个处理方法，我们可以通过调用sigaction来设置我们自己的信号处理程序，也可以通过设置SIG_IGN来忽略信号，设置SIG_DFL来设置默认的处理方法。<br><br>僵尸进程<br>设置进程为僵尸状态的目的是为了维护子进程的信息(子进程ID、终止状态和子进程的资源利用信息)。如果一个进程终止，且该进程仍有子进程处于僵尸状态，则所有僵尸进程的父进程设为init进程。僵尸进程占用内核空间，所以我们应该避免进程变为僵尸进程，方法是wait waitpid系统调用。可以设置信号SIGCHLD的信号处理程序，在此信号处理程序里调用wait或waitpid。这样可以避免僵尸进程。<br>在某些系统上这样作可能会导致服务器进程错误。原因是服务器子进程终止后，向父进程发送一个SIGCHLD信号，导致accept调用被中断，某些系统在信号处理程序执行完后不会重启accept调用，而是返回EINTR错误。由于我们的服务程序没有处理这种错误，所以会导致错误。为了移植性，当我们编写信号处理程序时，必须对慢系统调用(可能常时间阻塞的系统调用)返回EINTR有所装备。收到EINTR错误时，自己来重启被中断的系统调用。<br><br>用waitpid来防止产生僵尸进程<br>waitpid的WNOHANG选项，通知内核在没有子进程终止时不要阻塞。<br>假如服务器程序有5个子进程，每个进程负责处理一个连接。则可能5个子进程同时终止，同时向父进程发送SIGCHLD信号。而信号处理程序只能对一个信号进行处理，只有一个子进程正常终止，其余4个子进程则成为僵尸进程。可以通过ps -s命令来进行验证的确有4个子进程成为了僵尸进程。解决方法就是，循环调用witpid(加上WNOHANG选项)。<br>网络编程时注意的三种情况:<br><span style="color: #e20000;">1 当派生子进程时，必须捕捉SIGCHLD信号，防止子进程结束时成为僵尸进程。</span><br style="color: #e20000;"><span style="color: #e20000;">2 当捕捉信号时，必须处理被中断的系统断用，因为有些系统不能重启被中断的系统调用，需要我们自己来重启。</span><br style="color: #e20000;"><span style="color: #e20000;">3 SIGCHLD信号的处理程序必须正确便学，应使用waitpid来避免多个子进程同时终止时，留下僵尸进程。</span>
<br>   <img src ="http://www.cppblog.com/sixinquan/aggbug/108164.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sixinquan/" target="_blank">sin</a> 2010-02-21 19:49 <a href="http://www.cppblog.com/sixinquan/archive/2010/02/21/108164.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UNP读书笔记二 常用TCP编程API</title><link>http://www.cppblog.com/sixinquan/archive/2010/02/21/108161.html</link><dc:creator>sin</dc:creator><author>sin</author><pubDate>Sun, 21 Feb 2010 11:08:00 GMT</pubDate><guid>http://www.cppblog.com/sixinquan/archive/2010/02/21/108161.html</guid><wfw:comment>http://www.cppblog.com/sixinquan/comments/108161.html</wfw:comment><comments>http://www.cppblog.com/sixinquan/archive/2010/02/21/108161.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/sixinquan/comments/commentRss/108161.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sixinquan/services/trackbacks/108161.html</trackback:ping><description><![CDATA[只是简单介绍下每个函数的作用，很容易通过参数名知道每个参数的意义。<br><br>int socket(int family, int type, int protocol);<br>此函数根据参数创建一个指定的套接口，返回套接口描述符。<br><br>int connect(int sockfd, const struct sockaddr *servaddr, socklen addrlen);<br>TCP客户调用此函数向服务器发起连接，激发三路握手过程，在连接建立或出错时返回。此函数导致客户端从CLOSED状态转到SYN_SENT状态，再到<br>ESTABLISHED状态。若函数调用失败，套接口sockfd不再可用，必须关闭。<br><br>int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);<br>此函数用来给套接口绑定套接口地址。服务器通常调用此函数，来指定IP地址和端口号。<br><br>int listen(int sockfd, int backlog);<br>此函数完成两件事:将一个套接口置为被动套接口，默认是主动套接口；指定此套接口排队的最大连接数。<br><br>int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);<br>一般服务器端调用此函数从已经建立连接的队列里返回下一个连接。若已连接队列为空，则进程睡眠。也返回对方的套接口地址。<br><br>int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);<br>当建立建立后(客户端connect成功，服务器端accept成功)，调用此函数来获得本地套接口地址。sockfd必须是已经建立连接的套接口描述符。<br><br>int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);<br>一般情况下，服务器端调用此函数来获取客户端套接口地址。虽然accept也返回客户端套接口地址，但是在并发服务器上fork exec后，子进程的存储映像被新的程序文件代替，这样子进程就无法取得由accept返回的客户端套接口地址结构。此时就需要调用getpeername。<br>  <img src ="http://www.cppblog.com/sixinquan/aggbug/108161.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sixinquan/" target="_blank">sin</a> 2010-02-21 19:08 <a href="http://www.cppblog.com/sixinquan/archive/2010/02/21/108161.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UNP读书笔记一   Socket编程的简单介绍!</title><link>http://www.cppblog.com/sixinquan/archive/2010/01/24/106310.html</link><dc:creator>sin</dc:creator><author>sin</author><pubDate>Sat, 23 Jan 2010 17:44:00 GMT</pubDate><guid>http://www.cppblog.com/sixinquan/archive/2010/01/24/106310.html</guid><wfw:comment>http://www.cppblog.com/sixinquan/comments/106310.html</wfw:comment><comments>http://www.cppblog.com/sixinquan/archive/2010/01/24/106310.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/sixinquan/comments/commentRss/106310.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sixinquan/services/trackbacks/106310.html</trackback:ping><description><![CDATA[<span style="font-weight: bold;">一 源代码编译</span><br>也是在网上找的源代码编译方法，也很简单。<br>首先，在http://www.unpbook.com/unpv13e.tar.gz下载源代码。<br><br><span style="font-weight: bold;">二 几个重要的数据结构和函数</span><br><br><span style="font-size: 12pt;">1 sockaddr和sockaddr_in结构</span><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">struct</span><span style="color: #000000;">&nbsp;sockaddr&nbsp;{<br>unsigned&nbsp;&nbsp;</span><span style="color: #0000ff;">short</span><span style="color: #000000;">&nbsp;&nbsp;sa_family;<br></span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;&nbsp;sa_data[</span><span style="color: #000000;">14</span><span style="color: #000000;">];<br>};<br><br></span><span style="color: #0000ff;">struct</span><span style="color: #000000;">&nbsp;&nbsp;sockaddr_in&nbsp;{<br></span><span style="color: #0000ff;">short</span><span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;&nbsp;sin_family;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>unsigned&nbsp;&nbsp;</span><span style="color: #0000ff;">short</span><span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;&nbsp;sin_port;<br></span><span style="color: #0000ff;">struct</span><span style="color: #000000;">&nbsp;&nbsp;in_addr&nbsp;&nbsp;sin_addr;<br>unsigned&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;&nbsp;sin_zero[</span><span style="color: #000000;">8</span><span style="color: #000000;">];<br>};<br><br></span><span style="color: #0000ff;">struct</span><span style="color: #000000;">&nbsp;&nbsp;in_addr&nbsp;{<br>unsigned&nbsp;&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;&nbsp;s_addr;<br>};</span></div>
<span style="font-size: 12pt;">这两个结构体大小一样，名字也比较像。Socket
API最初设计的时候，想设计的尽可能的通用(在&lt;&lt;TCP/IP进行网际互联&gt;&gt;里有提到过)，不只限于TCP/IP协议，所
以sockaddr结构体只定义了协议族字段和预留了14个字节来表示某个协议地址(协议地址占多少位取决于协议的设计，所以只能预留14个字节)。
sockaddr_in结构体则像是为TCP/IP协议地址设计的结构体，有一个端口号和IP地址来指定。这也只是我的理解，并不一定对。<br>实际编程中，bind、connect、recvfrom、sendto等Socket API用到的是sockaddr结构体。由于现在TCP/IP协议已经成为标准，多数情况下用到的都是表示TCP/IP地址的sockaddr_in结构。<br><br></span>2 htons htonl 函数<br>将主机字节序转化为网络字节序。这是由于，不同主机可能使用不同的方式来存储字节，Inel机器就是小尾端，需要转化为一种统一的序列，方便在网络上传输处理，就是网络字节序。<br><br>3 inet_addr 函数<br>将"192.168.1.100"这样的字符串转化为IP地址，inet_addr返回结果已经是网络字节序，不需要再转化。<br><br><br><span style="font-weight: bold;">三 一个简单的客户/服务器程序</span>  <img src ="http://www.cppblog.com/sixinquan/aggbug/106310.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sixinquan/" target="_blank">sin</a> 2010-01-24 01:44 <a href="http://www.cppblog.com/sixinquan/archive/2010/01/24/106310.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>