項目要求:手機的遙控器界面,通過UDP/TCP協(xié)議制定的指令竹勉,連接電視盒子飞盆,操控電視進行換臺,播放,暫停吓歇,調(diào)整聲音的操作孽水,同時實現(xiàn)小屏投大屏,即手機播放的視頻可以投到電視上播放城看。
做項目之前女气,我們需要知道
1、如何在oc中使用UDP/TCP協(xié)議测柠,他們是什么
2炼鞠、UDP/TCP指令是什么
3、我們要如何使手機和電視盒子連接
解決問題一:Socket?
網(wǎng)絡(luò)七層由下往上分別為物理層轰胁、數(shù)據(jù)鏈路層簇搅、網(wǎng)絡(luò)層、傳輸層软吐、會話層、表示層和應(yīng)用層吟税。http協(xié)議對應(yīng)于應(yīng)用層凹耙,tcp協(xié)議對應(yīng)于傳輸層,ip協(xié)議對應(yīng)于網(wǎng)絡(luò)層肠仪,三者本質(zhì)上沒有可比性肖抱。? 何況HTTP協(xié)議是基于TCP連接的。TCP/IP是傳輸層協(xié)議异旧,主要解決數(shù)據(jù)如何在網(wǎng)絡(luò)中傳輸意述;而HTTP是應(yīng)用層協(xié)議,主要解決如何包裝數(shù)據(jù)吮蛹。
我們在傳輸數(shù)據(jù)時荤崇,可以只使用傳輸層(TCP/IP),但是那樣的話潮针,由于沒有應(yīng)用層术荤,便無法識別數(shù)據(jù)內(nèi)容,如果想要使傳輸?shù)臄?shù)據(jù)有意義每篷,則必須使用應(yīng)用層 協(xié)議瓣戚,應(yīng)用層協(xié)議很多,有HTTP焦读、FTP子库、TELNET等等,也可以自己定義應(yīng)用層協(xié)議矗晃。WEB使用HTTP作傳輸層協(xié)議仑嗅,以封裝HTTP文本信息,然 后使用TCP/IP做傳輸層協(xié)議將它發(fā)送到網(wǎng)絡(luò)上。Socket是對TCP/IP協(xié)議的封裝无畔,Socket本身并不是協(xié)議啊楚,而是一個調(diào)用接口(API),通過套接字Socket浑彰,我們才能使用TCP/IP協(xié)議恭理。(當然關(guān)于UDP/TCP區(qū)別什么的大家應(yīng)該也都了解了 這里就不贅述了么么噠)
解決問題二 指令?
所謂的指令這里也就是電視盒子端的開發(fā)人員郭变,制定好的一種規(guī)則颜价,例如按住遙控器的“上箭頭”,可能會規(guī)定指令是“1”诉濒,只要接收到我們客戶端發(fā)送“1”(當然要編碼的周伦,稍后會說哦),盒子就會執(zhí)行“向上”的行為(可能是換臺)未荒。
命令
0x11111111 (app傳送操作命令)
格式: 0x11111111 + {int cmd} (操作命令)
操作命令 1:POW OFF 2:HOME 3:MUTE 4:MENU 5:RETURN 6:VOL_UP 7:VOL_DOWN 8:ARR_UP 9:ARR_DOWN 10:ARR_RIGHT 11:ARR_LEFT 12:BUT_OK
解決問題3? 建立socket連接
建立Socket連接至少需要一對套接字专挪,其中一個運行于客戶端,稱為ClientSocket片排,另一個運行于服務(wù)器端寨腔,稱為ServerSocket。
套接字之間的連接過程分為三個步驟:服務(wù)器監(jiān)聽率寡,客戶端請求迫卢,連接確認。
服務(wù)器監(jiān)聽:服務(wù)器端套接字并不定位具體的客戶端套接字冶共,而是處于等待連接的狀態(tài)乾蛤,實時監(jiān)控網(wǎng)絡(luò)狀態(tài),等待客戶端的連接請求捅僵。
客戶端請求:指客戶端的套接字提出連接請求家卖,要連接的目標是服務(wù)器端的套接字。為此命咐,客戶端的套接字必須首先描述它要連接的服務(wù)器的套接字篡九,指出服務(wù)器端套接字的地址和端口號,然后就向服務(wù)器端套接字提出連接請求醋奠。
連接確認:當服務(wù)器端套接字監(jiān)聽到或者說接收到客戶端套接字的連接請求時榛臼,就響應(yīng)客戶端套接字的請求,建立一個新的線程窜司,把服務(wù)器端套接字的描述發(fā)給客戶 端沛善,一旦客戶端確認了此描述,雙方就正式建立連接塞祈。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽狀態(tài)金刁,繼續(xù)接收其他客戶端套接字的連接請求。
上面的可能太官方了,說白了尤蛮,你需要有以下的步驟來使客戶端和盒子(服務(wù)器)建立連接媳友。
1、首先你需要發(fā)送廣播产捞,來找誰是盒子
2醇锚、找到以后,服務(wù)器會返回給你坯临,它自己的ip和端口號
3焊唬、以后你發(fā)的指令祷肯,就往這個ip和端口號發(fā)送就好啦
那么廢話不多說上代碼辜羊,因為我做的項目是遵循UDP協(xié)議的缚陷,所以代碼是基于UDP寫的仇冯,關(guān)于Sorket這里有一個封裝好的類庫GCDAsyncUdpSocket,下載地址如下http://download.csdn.net/download/xiaoamani/7455735(如果你不能下載也可百度搜索月弛,GitHub上也有但是是demo鸥咖,不是只是類庫符喝,當然你也可以和我要哈)
代碼代碼代碼
-(void)createClientUdpSocket
{
dispatch_queue_tdQueue =dispatch_get_global_queue(0,0);
//1.創(chuàng)建一個udp socket用來和服務(wù)器端進行通訊
sendUdpSocket= [[GCDAsyncUdpSocketalloc]initWithDelegate:selfdelegateQueue:dQueuesocketQueue:nil];
//2.banding一個端口(可選),如果不綁定端口,那么就會隨機產(chǎn)生一個隨機的電腦唯一的端口
//端口數(shù)字范圍(1024,2^16-1)
[sendUdpSocketbindToPort:8085error:nil];
[sendUdpSocketenableBroadcast:YESerror:nil];
//3.等待接收對方的消息
[sendUdpSocketreceiveOnce:nil];
}
- (void) sendMsg {
intcommNum =0x55f03651;
NSMutableData*myData = [[NSMutableDataalloc]init];
[myDataappendBytes:&commNumlength:sizeof(commNum)];
NSString*host =@"255.255.255.255"; //發(fā)送廣播
uint16_tport =49555;//規(guī)定的端口號
//開始發(fā)送
//改函數(shù)只是啟動一次發(fā)送它本身不進行數(shù)據(jù)的發(fā)送,而是讓后臺的線程慢慢的發(fā)送也就是說這個函數(shù)調(diào)用完成后,數(shù)據(jù)并沒有立刻發(fā)送,異步發(fā)送
[sendUdpSocketsendData:myData toHost:hostport:port withTimeout:1tag:100];
}
#pragma mark -GCDAsyncUdpSocketDelegate
-(void)udpSocket:(GCDAsyncUdpSocket*)sock didSendDataWithTag:(long)tag{
if(tag ==100) {
NSLog(@"表示標記為100的數(shù)據(jù)發(fā)送完成了");
}
}
-(void)udpSocket:(GCDAsyncUdpSocket*)sock didNotSendDataWithTag:(long)tag dueToError:(NSError*)error{
NSLog(@"標記為tag %ld的發(fā)送失敗失敗原因%@",tag, error);
}
//接受盒子服務(wù)器的返回端口號和ip以及一些數(shù)據(jù)
-(void)udpSocket:(GCDAsyncUdpSocket*)sock didReceiveData:(NSData*)data fromAddress:(NSData*)address withFilterContext:(id)filterContext{
NSString*ip = [GCDAsyncUdpSockethostFromAddress:address];
uint16_tport = [GCDAsyncUdpSocketportFromAddress:address];
//繼續(xù)來等待接收下一次消息
_ipNum= ip;
_myPort= port;
[sockreceiveOnce:nil];
//dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//[self sendBackToHost:ip port:port withMessage:s];
//});
}
//開始向接收到的ip和端口號發(fā)送指令myIpum
- (void) sendMsgTime :(NSString*)myIpum andPort:(uint16_t)myPort andUid:(NSString*)myUid{
intcommNumber =0x11111111;
NSMutableData*myDa = [[NSMutableDataalloc]init];
[myDaappendBytes:&commNumberlength:sizeof(commNumber)];
NSString*host = myIpum;
uint16_tport = myPort;
_romeId= myUid;
//開始發(fā)送
//改函數(shù)只是啟動一次發(fā)送它本身不進行數(shù)據(jù)的發(fā)送,而是讓后臺的線程慢慢的發(fā)送也就是說這個函數(shù)調(diào)用完成后,數(shù)據(jù)并沒有立刻發(fā)送,異步發(fā)送
[sendUdpSocketsendData:myDatoHost:hostport:portwithTimeout:1tag:100];
}
ok截至到這里 ?大家就應(yīng)該明白了如何接受服務(wù)器的數(shù)據(jù)谤祖,和發(fā)送指令爵赵。那么投屏的,道理一樣泊脐,只是需要發(fā)送指令的時候,把點播視頻url編碼后也發(fā)送過去烁峭,直播的videoId也發(fā)送過去(至于編碼我會在研究容客,寫一篇文章,歡迎大家到時候看看指點)當然每個項目的規(guī)定不一樣约郁,我這不是一定的缩挑,只是思路大家明白就好。這是我的第一篇文章鬓梅,可能會有許多的不足供置,希望大家指正,哈哈哈绽快,我今年剛畢業(yè)芥丧,10月份之前公司有點變故辭職了,現(xiàn)在找工作幾乎沒面試坊罢,很多人勸我轉(zhuǎn)行续担,說我沒經(jīng)驗,iOS已經(jīng)發(fā)展不好了活孩,可是我覺得物遇,如果有技術(shù)能鉆研,就算不發(fā)展的那一天,我也覺得我沒白學iOS询兴,因為我得到了那份滿足感乃沙,開發(fā)的滿足感,我享受打碼诗舰。