<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://www.jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://www.jackxiang.com/post//</link>
<title><![CDATA[Socket 简易入门手册]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Sun, 25 Nov 2007 03:10:19 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	介绍 <br/>　　当你进入 UNIX 的神秘世界后，立刻会发现越来越多的东西难以理解。对于大多数人来说，BSD socket 的概念就是其中一个。这是一个很短的教程来解释他们是什么、他们如何工作并给出一些简单的代码来解释如何使用他们。 <br/><br/>类比 (什么是 socket ？) <br/>　　socket 是进行程序间通讯(IPC)的 BSD 方法。这意味着 socket 用来让一个进程和其他的进程互通信息，就象我们用电话来和其他的人交流一样。 <br/><br/>用电话来比喻是很恰当的，我们在后面将一直用电话这个概念来描叙 socket 。 <br/><br/>装上你的新电话(怎样侦听？) <br/>　　一个人要能够收到别人打给他的电话，首先他要装上一门电话。同样，你必须先建立 socket 以侦听线路。这个过程包含几个步骤。首先，你要建立一个新的 socket，就象先装上电话一样。socket() 命令就完成这个工作。 <br/><br/>因为 sockets 有几种类型，你要注明你要建立什么类型的。你要做一个选择是 socket 的地址格式。如同电话有音频和脉冲两种形式一样，socket 有两个最重要的选项是 AF_UNIX 和 IAF_INET。AF_UNIX 就象 UNIX 路径名一样识别 sockets。这种形式对于在同一台机器上的 IPC 很有用。而 AF_INET 使用象 192.9.200.10 这样被点号隔开的四个十进制数字的地址格式。除了机器地址以外，还可以利用端口号来允许每台机器上的多个 AF_INET socket。我们这里将着重于 AF_INET 方式，因为他很有用并广泛使用。 <br/><br/>另外一个你必须提供的参数是 socket 的类型。两个重要的类型是 SOCK_STREAM 和 SOCK_DGRAM。 SOCK_STREAM 表明数据象字符流一样通过 socket 。而 SOCK_DGRAM 则表明数据将是数据报(datagrams)的形式。我们将讲解 SOCK_STREAM sockets，他很常见并易于使用。 <br/><br/>在建立 socket 后，我们就要提供 socket 侦听的地址了。就象你还要个电话号码来接电话一样。bind() 函数来处理这件事情。 <br/><br/>SOCK_STREAM sockets 让连接请求形成一个队列。如果你忙于处理一个连接，别的连接请求将一直等待到该连接处理完毕。listen() 函数用来设置最大不被拒绝的请求数（一般为5个）。一般最好不要使用 listen() 函数。 <br/><br/>下面的代码说明如何利用 socket()、 bind() 和 listen() 函数建立连接并可以接受数据。 <br/><br/><br/>　　/* code to establish a socket; originally from bzs@bu-cs.bu.edu <br/>　　 */ <br/><br/>int establish(unsigned short portnum) <br/>　　{ char myname[MAXHOSTNAME+1]; <br/>　　 int s; <br/>　　 struct sockaddr_in sa; <br/>　　 struct hostent *hp; <br/><br/>memset(&amp;sa, 0, sizeof(struct sockaddr_in)); /* clear our address */ <br/>　　 gethostname(myname, MAXHOSTNAME); /* who are we? */ <br/>　　 hp= gethostbyname(myname); /* get our address info */ <br/>　　 if (hp == NULL) /* we don&#92;t exist !? */ <br/>　　 return(-1); <br/>　　 sa.sin_family= hp-&gt;h_addrtype; /* this is our host address */ <br/>　　 sa.sin_port= htons(portnum); /* this is our port number */ <br/>　　 if ((s= socket(AF_INET, SOCK_STREAM, 0)) /* obligatory includes */ <br/>　　#include <br/>　　#include <br/>　　#include <br/>　　#include <br/>　　#include <br/>　　#include <br/>　　#include <br/>　　#include <br/><br/>#define PORTNUM 50000 /* random port number, we need something */ <br/><br/>void fireman(void); <br/>　　void do_something(int); <br/><br/>main() <br/>　　{ int s, t; <br/><br/>if ((s= establish(PORTNUM)) 0) <br/>　　 ; <br/>　　} <br/><br/>/* this is the function that plays with the socket. it will be called <br/>　　 * after getting a connection. <br/>　　 */ <br/>　　void do_something(int s) <br/>　　{ <br/>　　 /* do your thing with the socket here <br/>　　 : <br/>　　 : <br/>　　 */ <br/>　　} <br/><br/>拨号 (如何调用 socket) <br/>　　现在你应该知道如何建立 socket 来接受调用了。那么如何调用呢？和电话一样，你要先有个电话。用 socket() 函数来完成这件事情，就象建立侦听的 socket 一样。 <br/><br/>在给 socket 地址后，你可以用 connect() 函数来连接侦听的 socket 了。下面是一段代码。 <br/><br/><br/>　　int call_socket(char *hostname, unsigned short portnum) <br/>　　{ struct sockaddr_in sa; <br/>　　 struct hostent *hp; <br/>　　 int a, s; <br/><br/>if ((hp= gethostbyname(hostname)) == NULL) { /* do we know the host&#92;s */ <br/>　　 errno= ECONNREFUSED; /* address? */ <br/>　　 return(-1); /* no */ <br/>　　 } <br/><br/>memset(&amp;sa,0,sizeof(sa)); <br/>　　 memcpy((char *)&amp;sa.sin_addr,hp-&gt;h_addr,hp-&gt;h_length); /* set address */ <br/>　　 sa.sin_family= hp-&gt;h_addrtype; <br/>　　 sa.sin_port= htons((u_short)portnum); <br/><br/>if ((s= socket(hp-&gt;h_addrtype,SOCK_STREAM,0)) 0) { <br/>　　 bcount += br; /* increment byte counter */ <br/>　　 buf += br; /* move buffer ptr for next read */ <br/>　　 } <br/>　　 else if (br &lt; 0) /* signal an error to the caller */ <br/>　　 return(-1); <br/>　　 } <br/>　　 return(bcount); <br/>　　} <br/><br/>相同的函数也可以写数据，留给我们的读者吧。 <br/><br/>挂起(结束) <br/>　　和你通过电话和某人交谈后一样，你要在 socket 间关闭连接。一般 close() 函数用来关闭每边的 socket 连接。如果一边的已经关闭，而另外一边却在向他写数据，则返回一个错误代码。 <br/><br/>世界语(交流的语言很重要) <br/>　　现在你可以在机器间联络了，可是要小心你所说的话。许多机器有自己的方言，如 ASCII 和 EBCDIC。更常见的问题是字节顺序问题。除非你一直传输的都是文本，否则你一定要注意这个问题。幸运的是，人们找出了解决的办法。 <br/><br/>在很久以前，人们争论哪种顺序更“正确”。现在必要时有相应的函数来转换。其中有 htons()、ntohs()、htonl() 和 ntohl()。在传输一个整型数据前，先转换一下。 <br/><br/><br/>　　i= htonl(i); <br/>　　write_data(s, &amp;i, sizeof(i)); <br/><br/>在读数据后，再变回来。 <br/><br/><br/>　　read_data(s, &amp;i, sizeof(i)); <br/>　　i= ntohl(i); <br/><br/>如果你一直坚持这个习惯，你将比别人少出错的机会。 <br/><br/>未来在你的掌握了(下一步？) <br/>　　就用我们刚才讨论的东西，你就可以写自己的通讯程序了。和对待所有的新生事物一样， 最好还是看看别人已经做了些什么。这里有许多关于 BSD socket 的东西可以参考。 <br/><br/>请注意，例子中没有错误检查，这在“真实”的程序中是很重要的。你应该对此充分重视。 
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] Socket 简易入门手册]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>