從基本的知識開始講解iPhone BSD Socket編程_第1頁
從基本的知識開始講解iPhone BSD Socket編程_第2頁
從基本的知識開始講解iPhone BSD Socket編程_第3頁
從基本的知識開始講解iPhone BSD Socket編程_第4頁
從基本的知識開始講解iPhone BSD Socket編程_第5頁
已閱讀5頁,還剩7頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

精品文檔-下載后可編輯從基本的知識開始講解iPhoneBSDSocket編程1初始化一個Socket

socket的英文原義是“孔”或“插座”。作為4BDSUNIX的進程通信機制,取后一種意思。通常也稱作“套接字”,用于描述IP地址和端口,是一個通信鏈的句柄。在Internet上的主機一般運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個Socket,并綁定到一個端口上,不同的端口對應于不同的服務。Socket正如其英文原意那樣,象一個多孔插座。一臺主機猶如布滿各種插座的房間,每個插座有一個編號,有的插座提供220伏交流電,有的提供110伏交流電,有的則提供有線電視節(jié)目??蛻糗浖⒉孱^插到不同編號的插座,就可以得到不同的服務。

首先,Socket是進行程序間通訊(IPC,InternetProcessCONnection)的BSD方法,這意味著Socket是用來讓一個進程和其他的進程互相通訊的,就像我們用電話來和其他人交流一樣。既然說Socket像個電話,那么如果要打電話首先就要安裝一部電話,“安裝電話”這個動作對BSDSocket來說就是初始化一個Socket,方法如下:intsocket(int,int,int);個int參數(shù)為Socket的地址方式,既然要“安裝電話”,那么就要首先確認所要安裝的電話是音頻的還是脈沖的。而如果要給BSDSocket安裝電話,有兩種類型可供讀者選擇:AF_UNIX和AF_INET,它們代表Socket的地址格式。如果選擇AF_UNIX,意味著需要為Socket提供一個類似Unix路徑的名稱,這個選項主要用于本地程序之間的socket通訊。第二個int參數(shù)為Socket的類型,“安裝電話”需要首先確定是裝有線的還是裝無線的,安裝Socket也一樣,在Socket中提供了兩種類型:SOCK_STREAM和SOCK_DGRAM。第三個int參數(shù)為所使用的協(xié)議,本文里使用0即可。“安裝電話”的代碼如下:if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){perror(“socket”);exit(1);}2BSDSocket扮演“客戶端”角色的操作

到現(xiàn)在為止,怎么安裝電話已經(jīng)清楚了。因為本文主要演示如何在iPhone上使用BSDSocket獲取內(nèi)容,更多的功能是“打電話”而不是“接電話”,所以下面主要講解BSDSocket扮演“客戶端”角色的操作。既然要“打電話”,那么首先要有打電話的對象,更確切的說需要一個“電話號碼”,BSDSocket中的“電話號碼”就是IP地址。更糟糕的情況是,如果只知道聯(lián)系人的名字而不知道電話號碼,那么還需要程序查找相應聯(lián)系人的電話號碼,根據(jù)聯(lián)系人姓名查找電話號碼的過程在BSDSocket中叫做DNS解析,代碼如下:-(NSString*)getIpAddressForHost:(NSString*)theHost{structhostent*host=gethostbyname([theHostUTF8String]);if(!host){herror(“resolv”);returnNULL;}structin_addr**list=(structin_addr**)host-h_addr_list;NSString*addressString=[NSStringstringWithCString:inet_ntoa(*list[0])];returnaddressString;}hostent是個結(jié)構(gòu)體,使用它需要#importnetdb.h,通過這個方法得到theHost域名的個有效的IP地址并返回。正確的“找到電話號碼”后,就需要“撥打電話”了,代碼如下:their_addr.sin_family=AF_INET;their_addr.sin_addr.s_addr=inet_addr([[selfgetIpAddressForHost:hostName]UTF8String]);NSLog(@“getIpAddressForHost:%@”,[selfgetIpAddressForHost:hostName]);their_addr.sin_port=htons(80);bzero((their_addr.sin_zero),8);intconn=connect(sockfd,(structsockaddr*)their_addr,sizeof(structsockaddr));NSLog(@“Connecterrnois:%d”,conn);筆者初試圖采用NHost進行主機域名的解析,奈何iPhone的這個類為private的,在application的開發(fā)中不可使用。如果“電話”能順利的接通,那么就可以進行“講話”了,反之則會斷開“電話連接if(conn!=-1){NSLog(@“Thentheconnisnot-1!”);NSMutableString*httpContent=[selfmakeHttpHeader:hostName];NSLog(@“httpCotentis:%@”,httpContent);if(contentSended!=nil)[httpContentappendFormat:contentSended];NSLog(@“Sendedcontentis:%@”,httpContent);NSData*data=[httpContentdataUsingEncoding:NSISOLatin1StringEncoding];ssize_tdataSended=send(sockfd,[databytes],[datalength],0);if(dataSended==[datalength]){NSLog(@“Datashavebeensendedover!”);}printf(“send%dbytesto%s\n”,dataSended,inet_ntoa(their_addr.sin_addr));NSMutableString*readString=[[NSMutableStringalloc]init];charreadBuffer[512];intbr=0;while((br=recv(sockfd,readBuffer,sizeof(readBuffer),0))sizeof(readBuffer)){NSLog(@“readdataslengthis:%d”,br);[readStringappendFormat:[NSStringstringWithCString:readBufferlength:br]];NSLog(@“Havareceiveddatasis:%@”,readString);}close(sockfd);}else{UIAlertView*alert=[[UIAlertViewalloc]initWithTitle:[@“Connectionfailedtohost”stringByAppendingString:hostName]message:@“Pleasecheckthehostnameinthepreferences.”delegate:selfcancelButtonTitle:@“OK”otherButtonTitles:nil];[alertshow];[alertrelease];}“講話”通過send(),“聽話”通過recv(),這個兩個函數(shù)的原型如下:intsend(intsockfd,constvoid*msg,intlen,intflags);intrecv(intsockfd,void*buf,intlen,unsignedintflags);可以看出,這兩個函數(shù)的參數(shù)基本相同。個參數(shù)為套接字的句柄。第二個參數(shù)為數(shù)據(jù)緩沖區(qū)。第三個參數(shù)為數(shù)據(jù)長度。一個參數(shù)有點特殊,這個參數(shù)是為了讓BSDSocket能支持“帶外數(shù)據(jù)”,何謂“帶外數(shù)據(jù)”?顧名思義,就是“帶內(nèi)以外的數(shù)據(jù)”,而帶內(nèi)數(shù)據(jù)就是常規(guī)的按照Socket字節(jié)流順序進行傳遞的數(shù)據(jù)。通常情況下,數(shù)據(jù)由連接的一端流到接收的一端,并且認為數(shù)據(jù)的所有字節(jié)都是排序的,晚寫入的字節(jié)絕不會早于先寫入的字節(jié)到達。請求帶外數(shù)據(jù)傳送需要把標識位置為MSG_OOB,如下:charbuf[64];intlen;ints;…send(s,buf,len,MSG_OOB);3調(diào)用close(sockfd)“掛斷電話”

至此,一個完整的“通話過程”已經(jīng)結(jié)束,別忘記調(diào)用close(sockfd)“掛斷電話”。下面筆者嘗試請求的,并把請求的頁面內(nèi)容打印到控制臺,所以需要對請求進行封裝,以支持HTTP協(xié)議。很簡單,只需要在請求的內(nèi)容前面加上相應的HTTP頭信息即可,如下:#defineHTTPMETHOD@“GET”#defineHTTPVERSION@“HTTP/1.1”#defineHTTPHOST@“Host”#defineKENTER@“\r\n”#defineKBLANK@“”-(NSMutableString*)makeHttpHeader:(NSString*)hostName{NSMutableString*header=[[NSMutableStringalloc]init];[headerappendFormat:HTTPMETHOD];[headerappendFormat:KBLANK];[headerappendFormat:@“/index.html”];[headerappendFormat:KBLANK];[headerappendFormat:HTTPVERSION];[headerappendFormat:KENTER];[headerappendFormat:HTTPHOST];[headerappendFormat:@“:”];[headerappendFormat:hostName];[headerappendFormat:KENTER];[headerappendFormat:KENTER];returnheader;}在上面的方法中,筆者封裝了HTTP頭信息,對HTTP不熟悉的同學可以先熟悉熟悉HTTP的格式,請求到的內(nèi)容打印如下:[Sessionstartedat2022-11-1215:40:02+0800.]2022-11-1215:40:04.691BSDHttpExample[3483:207]getIpAddressForHost:02022-11-1215:40:04.725BSDHttpExample[3483:207]Connecterrnois:02022-11-1215:40:04.727BSDHttpExample[3483:207]Thentheconnisnot-1!2022-11-1215:40:04.735BSDHttpExample[3483:207]httpCotentis:GET/index.htmlHTTP/1.1Host:2022-11-1215:40:04.736BSDHttpExample[3483:207]Sendedcontentis:GET/index.htmlHTTP/1.1Host:2022-11-1215:40:04.736BSDHttpExample[3483:207]Datashavebeensendedover!send48bytesto02022-11-1215:40:04.764BSDHttpExample[3483:207]readdataslengthis:3632022-11-1215:40:04.765BSDHttpExample[3483:207]Havareceiveddatasis:HTTP/1.1200OKDate:Thu,12Nov202207:40:05GMTServer:BWS/1.0Content-Length:3520Content-Type:text/html;charset=gb2312Cache-Control:privateExpires:Thu,12Nov202207:40:05GMTSet-Cookie:BAIDUID=9B024266ADD3B52AC8367A2BDD1676E5:FG=1;expires=Thu,12-Nov-3907:40:05GMT;path=/;domain=.P3P:CP=“OTIDSPCORIVAOURINDCOM”2022-11-1215:40:04.766BSDHttpExample[3483:207]viewhasbeenloaded!4頭文件

為了造福大家,筆者附上完整的代碼,頭文件如下:////BSDHttpExampleViewController.h//BSDHttpExample////Createdbysundfsun2022on09-11-12.//Copyright__MyCompanyName__2022.Allrightsreserved.//#importUIKit/UIKit.h#defineMYPORT4880#importstdio.h#importstdlib.h#importunistd.h#importarpa/inet.h#importsys/types.h#importsys/socket.h#importnetdb.h@interfaceBSDHttpExampleViewController:UIViewController{intsockfd;structsockaddr_intheir_addr;}@end實現(xiàn)文件如下:////BSDHttpExampleViewController.m//BSDHttpExample////Createdbysundfsun2022on09-11-12.//Copyright__MyCompanyName__2022.Allrightsreserved.//#import“BSDHttpExampleViewController.h”@implementationBSDHttpExampleViewController#defineHTTPMETHOD@“GET”#defineHTTPVERSION@“HTTP/1.1”#defineHTTPHOST@“Host”#defineKENTER@“\r\n”#defineKBLANK@“”/*//Thedesignatedinitializer.Overridetoperformsetupthatisrequiredbeforetheviewisloaded.-(id)initWithNibName:(NSString*)nibNameOrNilbundle:(NSBundle*)nibBundleOrNil{if(self=[superinitWithNibName:nibNameOrNilbundle:nibBundleOrNil]){//Custominitialization}returnself;}*//*//ImplementloadViewtocreateaviewhierarchyprogrammatically,withoutusinganib.-(void)loadView{}*/voiderror_handle(char*errorMsg){fputs(errorMsg,stderr);fputc(‘\n',stderr);exit(1);}-(NSMutableString*)makeHttpHeader:(NSString*)hostName{NSMutableString*header=[[NSMutableStringalloc]init];[headerappendFormat:HTTPMETHOD];[headerappendFormat:KBLANK];[headerappendFormat:@“/index.html”];[headerappendFormat:KBLANK];[headerappendFormat:HTTPVERSION];[headerappendFormat:KENTER];[headerappendFormat:HTTPHOST];[headerappendFormat:@“:”];[headerappendFormat:hostName];[headerappendFormat:KENTER];[headerappendFormat:KENTER];returnheader;}-(NSString*)getIpAddressForHost:(NSString*)theHost{structhostent*host=gethostbyname([theHostUTF8String]);if(!host){herror(“resolv”);returnNULL;}structin_addr**list=(structin_addr**)host-h_addr_list;NSString*addressString=[NSStringstringWithCString:inet_ntoa(*list[0])];returnaddressString;}-(void)Connect:(NSString*)hostNamecontent:(NSString*)contentSended{if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){perror(“socket”);exit(1);}//NSHost*host=[NSHosthostWithName:hostName];//if(host)//{their_addr.sin_family=AF_INET;//their_addr.sin_addr.s_addr=inet_addr([[hostaddress]UTF8String]);their_addr.sin_addr.s_addr=inet_addr([[selfgetIpAddressForHost:hostName]UTF8String]);NSLog(@“getIpAddressForHost:%@”,[selfgetIpAddressForHost:hostName]);their_addr.sin_port=htons(80);bzero((their_addr.sin_zero),8);intconn=connect(sockfd,(structsockaddr*)their_addr,sizeof(structsockaddr));NSLog(@“Connecterrnois:%d”,conn);if(conn!=-1){NSLog(@“Thentheconnisnot-1!”);NSMutableString*httpContent=[selfmakeHttpHeader:hostName];NSLog(@“httpCotentis:%@”,httpContent);if(contentSended!=nil)[httpContentappendFormat:contentSended];NSLog(@“Sendedcontentis:%@”,httpContent);NSData*data=[httpContentdataUsingEncoding:NSISOLatin1StringEncoding];ssize_tdataSended=send(sockfd,[databytes],[datalength],0);if(dataSended==[datalength]){NSLog(@“Datashavebeensendedover!”);}printf(“send%dbytesto%s\n”,dataSended,inet_ntoa(their_addr.sin_addr));NSMutableString*readString=[[NSMutableStringalloc]init];charreadBuffer[512];intbr=0;while((br=recv(sockfd,readBuffer,sizeof(readBuffer),0))sizeof(readBuffer)){NSLog(@“readdataslengthis:%d”,br);[readStringappendFormat:[NSStringstringWithCString:readBufferlength:br]];NSLog(@“Havareceiveddatasis:%@”,readString);}close(sockfd);}else{UIAlertView*alert=[[UIAlertViewalloc]initWithTitle:[@“Connectionfailedtohost”stringByAppendingString:hostName]message:@“Pleasecheckthehostnameinthepreferences.”delegate:selfcancelButtonTitle:@“OK”otherButtonTitles:nil];[alertshow];[alertrelease];}/*}else{UIAlertView*alert=[[UIAlertViewalloc]initWithTitle:[@“Couldnotlookuphost”stringByAppendin

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論