iPhone开发中BSD Socket轻松学习教程

移动开发 iOS
iPhone开发中BSD Socket轻松学习是本文要介绍的内容,主要是来学习iphone开发中线程的学习。在进行iphone开发通讯程序中,不可避免的要利用socket通讯,除了iPhone自带的CFSocket类接口之外,我们还可以基于BSD Socket来进行通讯程式的开发。

iPhone开发BSD Socket轻松学习是本文要介绍的内容,主要是来学习iphone开发中线程的学习。在进行iphone开发通讯程序中,不可避免的要利用socket通讯,除了iPhone开发中自带的CFSocket类接口之外,我们还可以基于BSD Socket来进行通讯程式的开发,而这篇文章简单介绍了BSD Socket的知识,笔者认为是一篇不错的入门文章,故转到blog上进行共享:

当你进入 UNIX 的神秘世界后,立刻会发现越来越多的东西难以理解。对于大多数人来说,BSD (Berkeley Software Distribution,伯克利软件套件是Unix的衍生系统,在1977至1995年间由加州大学伯克利分校开发和发布的) socket 的概念就是其中一个。这是一个很短的教程来解释他们是什么、他们如何工作并给出一些简单的代码来解释如何使用他们。

类比 (什么是 socket ?)

socket 是进行程序间通讯(IPC,Internet Process Connection)的 BSD 方法。这意味着 socket 用来让一个进程和其他的进程互通信息,就象我们用电话来和其他的人交流一样。

用电话来比喻是很恰当的,我们在后面将一直用电话这个概念来描叙 socket 。

装上你的新电话(怎样侦听?)

一个人要能够收到别人打给他的电话,首先他要装上一门电话。同样,你必须先建立 socket 以侦听线路。这个过程包含几个步骤。首先,你要建立一个新的 socket,就象先装上电话一样。socket() 命令就完成这个工作。

因为 sockets 有几种类型,你要注明你要建立什么类型的。你要做一个选择是 socket 的地址格式。如同电话有音频和脉冲两种形式一样,socket 有两个最重要的选项是 AF_UNIX 和 IAF_INET。AF_UNIX 就象 UNIX 路径名一样识别 sockets。这种形式对于在同一台机器上的 IPC 很有用。而 AF_INET 使用象 192.9.200.10 这样被点号隔开的四个十进制数字的地址格式。除了机器地址以外,还可以利用端口号来允许每台机器上的多个 AF_INET socket。我们这里将着重于 AF_INET 方式,因为他很有用并广泛使用。

另外一个你必须提供的参数是 socket 的类型。两个重要的类型是 SOCK_STREAM 和 SOCK_DGRAM。 SOCK_STREAM 表明数据象字符流一样通过 socket 。而 SOCK_DGRAM 则表明数据将是数据报(datagrams)的形式。我们将讲解 SOCK_STREAM sockets,他很常见并易于使用。

在建立 socket 后,我们就要提供 socket 侦听的地址了。就象你还要个电话号码来接电话一样。bind() 函数来处理这件事情。

SOCK_STREAM sockets 让连接请求形成一个队列。如果你忙于处理一个连接,别的连接请求将一直等待到该连接处理完毕。listen() 函数用来设置最大不被拒绝的请求数(一般为5个)。一般最好不要使用 listen() 函数。

下面的代码说明如何利用 socket()、 bind() 和 listen() 函数建立连接并可以接受数据。

  1. int establish(unsigned short portnum)  
  2. { char   myname[MAXHOSTNAME+1];  
  3.   int    s;  
  4.   struct sockaddr_in sa;  
  5.   struct hostent *hp;  
  6.   memset(&sa, 0, sizeof(struct sockaddr_in));  
  7.   gethostname(myname, MAXHOSTNAME);            
  8.   hpgethostbyname(myname);                    
  9.   if (hp == NULL)                              
  10.     return(-1);  
  11.   sa.sin_familyhp->h_addrtype;                
  12.   sa.sin_porthtons(portnum);                  
  13.   if ((ssocket(AF_INET, SOCK_STREAM, 0)) < 0)  
  14.     return(-1);  
  15.   if (bind(s,&sa,sizeof(struct sockaddr_in)) < 0) {  
  16.     close(s);  
  17.     return(-1);                                
  18.   }  
  19.   listen(s, 3);                                
  20.   return(s);  

在建立完 socket 后,你要等待对该 socket 的调用了。accept() 函数为此目的而来。调用 accept() 如同在电话铃响后提起电话一样。Accept() 返回一个新的连接到调用方的 socket 。

下面的代码演示使用是个演示。

  1. int get_connection(int s)  
  2. { int t;                    
  3.   if ((t = accept(s,NULL,NULL)) < 0)    
  4.     return(-1);  
  5.   return(t);  

和电话不同的是,在你处理先前的连接的时候,你还可以接受调用。为此,一般用 fork 来处理每个连接。下面的代码演示如何使用 establish() 和 get_connection() 来处理多个连接。

  1. #include          
  2. #include   
  3. #include   
  4. #include   
  5. #include   
  6. #include   
  7. #include   
  8. #include   
  9. #include   
  10. #define PORTNUM 50000  
  11. void fireman(void);  
  12. void do_something(int);  
  13. main()  
  14. { int s, t;  
  15.   if ((sestablish(PORTNUM)) < 0) {    
  16.     perror("establish");  
  17.     exit(1);  
  18.   }  
  19.   signal(SIGCHLD, fireman);            
  20.   for (;;) {                            
  21.     if ((tget_connection(s)) < 0) {  
  22.       if (errno == EINTR)              
  23.         continue;                      
  24.       perror("accept");                
  25.       exit(1);  
  26.     }  
  27.     switch(fork()) {                    
  28.     case -1 :                          
  29.       perror("fork");  
  30.       close(s);  
  31.       close(t);  
  32.       exit(1);  
  33.     case 0 :                            
  34.       close(s);  
  35.       do_something(t);  
  36.       exit(0);  
  37.     default :                          
  38.       close(t);                        
  39.       continue;  
  40.     }  
  41.   }  
  42. }  
  43. void fireman(void)  
  44. {  
  45.   while (waitpid(-1, NULL, WNOHANG) > 0)  
  46.     ;  
  47. }  
  48. void do_something(int s)  
  49. {  

拨号 (如何调用 socket)

现在你应该知道如何建立 socket 来接受调用了。那么如何调用呢?和电话一样,你要先有个电话。用 socket() 函数来完成这件事情,就象建立侦听的 socket 一样。

在给 socket 地址后,你可以用 connect() 函数来连接侦听的 socket 了。下面是一段代码。

  1. int call_socket(char *hostname, unsigned short portnum)  
  2. { struct sockaddr_in sa;  
  3.   struct hostent     *hp;  
  4.   int a, s;  
  5.  
  6.   if ((hpgethostbyname(hostname)) == NULL) {  
  7.     errnoECONNREFUSED;                        
  8.     return(-1);                                  
  9.   }  
  10.  
  11.   memset(&sa,0,sizeof(sa));  
  12.   memcpy((char *)&sa.sin_addr,hp->h_addr,hp->h_length);  
  13.   sa.sin_familyhp->h_addrtype;  
  14.   sa.sin_porthtons((u_short)portnum);  
  15.  
  16.   if ((ssocket(hp->h_addrtype,SOCK_STREAM,0)) < 0)    
  17.     return(-1);  
  18.   if (connect(s,&sa,sizeof sa) < 0) {                    
  19.     close(s);  
  20.     return(-1);  
  21.   }  
  22.   return(s);  

这个函数返回一个可以流过数据的 socket 。

谈话(如何通过 sockets 交谈)

好了,你在要传输数据的双方建立连接了,现在该传输数据了。read() 和 write() 函数来处理吧。除了在 socket 读写和文件读写中的一个区别外,和处理一般的文件一样。区别是你一般不能得到你所要的数目的数据。所以你要一直循环到你需要的数据的到来。一个简单的例子:将一定的数据读到缓存。

  1. int read_data(int s,      
  2.               char *buf,  
  3.               int n        
  4.              )  
  5. { int bcount;  
  6.   int br;      
  7.   bcount0;  
  8.   br0;  
  9.   while (bcount < n) {              
  10.     if ((brread(s,buf,n-bcount)) > 0) {  
  11.       bcount += br;                  
  12.       buf += br;                    
  13.     }  
  14.     else if (br < 0)                
  15.       return(-1);  
  16.   }  
  17.   return(bcount);  

相同的函数也可以写数据,留给我们的读者吧。

挂起(结束)

和你通过电话和某人交谈后一样,你要在 socket 间关闭连接。一般 close() 函数用来关闭每边的 socket 连接。如果一边的已经关闭,而另外一边却在向他写数据,则返回一个错误代码。

世界语(交流的语言很重要)

现在你可以在机器间联络了,可是要小心你所说的话。许多机器有自己的方言,如 ASCII 和 EBCDIC。更常见的问题是字节顺序问题。除非你一直传输的都是文本,否则你一定要注意这个问题。幸运的是,人们找出了解决的办法。

在很久以前,人们争论哪种顺序更“正确”。现在必要时有相应的函数来转换。其中有 htons()、ntohs()、htonl() 和 ntohl()。在传输一个整型数据前,先转换一下。

  1. ihtonl(i);  
  2. write_data(s, &i, sizeof(i)); 

在读数据后,再变回来。

  1. read_data(s, &i, sizeof(i));  
  2. intohl(i); 

如果你一直坚持这个习惯,你将比别人少出错的机会。

未来在你的掌握了(下一步?)

就用我们刚才讨论的东西,你就可以写自己的通讯程序了。和对待所有的新生事物一样, 最好还是看看别人已经做了些什么。这里有许多关于 BSD socket 的东西可以参考。

请注意,例子中没有错误检查,这在“真实”的程序中是很重要的。你应该对此充分重视。

小结:关于iPhone开发BSD Socket轻松学习教程的内容介绍完了,希望通过本文的学习能对你有所帮助!

责任编辑:zhaolei 来源: 新浪博客
相关推荐

2011-08-09 09:57:59

iPhone服务器Socket

2011-07-27 16:46:04

iPhone iPhone破解 MacPort

2011-08-10 15:48:10

iPhone网络

2011-08-09 17:12:30

iPhoneCFRunLoop

2011-08-15 13:44:07

iPhone开发UITableView

2011-08-05 16:10:31

iPhone 网络 NSURLConne

2011-08-05 16:31:47

iPhone 数据库

2011-08-19 09:49:03

iPhone开发Three20 NetTTRequestLo

2011-08-02 17:37:01

IPhone开发 环境搭建

2011-08-11 16:19:11

iPhoneCocoa

2011-08-12 09:48:24

iPhoneCoreLocatio定位

2011-08-10 18:24:22

iPhone 图形 绘图

2011-07-08 16:02:24

iphone

2011-07-08 14:58:16

iPhone Xcode iOS

2011-08-12 18:18:03

iPhone开发UIPageContr按钮

2015-03-10 13:43:00

JavaSocket编程编程

2011-07-21 10:29:18

iPhone 开发

2011-08-09 13:10:32

iPhone地图开发

2011-08-08 10:10:14

iPhone开发 图片 方法

2011-08-01 18:27:58

iPhone开发 UISearchBa
点赞
收藏

51CTO技术栈公众号