Wifi通訊-(4)WIFI通訊客戶端端搭建

WIFI通訊客戶端搭建

  • 客戶的職責(zé)主要做三件事遮晚,一:連接服務(wù)端 二:接收來(lái)自服務(wù)端的數(shù)據(jù) 三:給服務(wù)端發(fā)送數(shù)據(jù)
  • [1.0-準(zhǔn)備工作]
  • [1.1-客戶端連接服務(wù)端]
  • [1.2-客戶端接收和發(fā)送數(shù)據(jù)到服務(wù)端]
  • [1.3-完整代碼及示例演示]

1.0-準(zhǔn)備工作

  • 筆者搭建了一個(gè)簡(jiǎn)單的界面,主要功能就是客戶端連接服務(wù)端監(jiān)聽(tīng)的網(wǎng)絡(luò)三娩,連接成功之后可以給服務(wù)端發(fā)送數(shù)據(jù)

1.1-客戶端連接服務(wù)端

  • 1.創(chuàng)建客戶端Socket
  • 2.客戶端連接服務(wù)端socket
    • socket本質(zhì)就是ip地址加端口號(hào)鸿脓,所以客戶端連接的也是ip地址加端口號(hào)抑钟,只不過(guò)這一個(gè)ip地址是服務(wù)端在局域網(wǎng)中的ip地址(上一小節(jié)獲取)野哭,端口號(hào)也是服務(wù)端所監(jiān)聽(tīng)的端口號(hào)(如果與服務(wù)端的ip地址和監(jiān)聽(tīng)的端口號(hào)不一致在塔,客戶端是無(wú)法連接的,因?yàn)檫@一個(gè)i地址的電腦的端口號(hào)沒(méi)有被監(jiān)聽(tīng))

//客戶端開(kāi)始連接
- (IBAction)wifiButtonClik:(UIButton *)sender {
    
    //1.創(chuàng)建客戶端socket
    //在socket通訊中拨黔,無(wú)論是客戶端還是服務(wù)端蛔溃,任何對(duì)象都是socket,類似于萬(wàn)物皆NSObject
    if (!self.clientSocket) {
        self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    }
    
    
    NSLog(@"%@",self.clientSocket.localHost);
    
    //2.連接服務(wù)端
    //注意:此處有兩個(gè)重點(diǎn)    1.這里的ip地址一定要是同一個(gè)局域網(wǎng)服務(wù)端的ip地址篱蝇,端口號(hào)也要與服務(wù)端連接的端口號(hào)一致   2.實(shí)際開(kāi)發(fā)中贺待,一般服務(wù)端的ip地址和所監(jiān)聽(tīng)的端口號(hào)都會(huì)在wifit通信協(xié)議中注明,這里只是筆者為了掩飾零截,所以隨便寫(xiě)了一個(gè)端口號(hào)1234麸塞,而這里的ip地址也是筆者為了掩飾給mac電腦設(shè)置了一個(gè)固定ip地址
    [self.clientSocket connectToHost:@"192.168.0.102" onPort:1234 error:nil];
    
    
}

1.2-客戶端接收和發(fā)送數(shù)據(jù)到服務(wù)端

  • ***1.客戶端連接成功之后,開(kāi)始讀取服務(wù)端的數(shù)據(jù)

  • 2.客戶端將接收到服務(wù)端的數(shù)據(jù)添加在數(shù)組涧衙,用于顯示(實(shí)際開(kāi)發(fā)中可能需要處理其他邏輯哪工,具體看需求)

  • 3.客戶端發(fā)送數(shù)據(jù)到服務(wù)端(實(shí)際開(kāi)發(fā)中數(shù)據(jù)格式由硬件工程師來(lái)定義)


#pragma mark- GCDAsyncSocketDelegate

//客戶端連接服務(wù)端成功
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
    //1.將開(kāi)始連接按鈕變?yōu)橐堰B接
    [self.clientButton setTitle:@"連接成功" forState:UIControlStateNormal];
    //2.發(fā)送數(shù)據(jù)按鈕開(kāi)啟交互
    self.senMsgButton.enabled = YES;
    
    //3.客戶端開(kāi)始讀取服務(wù)端的數(shù)據(jù)
    [self.clientSocket readDataWithTimeout:-1 tag:0];
}



//客戶端接收數(shù)據(jù)成功
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"客戶端接發(fā)送數(shù)據(jù):%@",str);
    
    //0.添加到數(shù)據(jù)源
    [self.tableArr addObject:data];
    
    //1.刷新界面
    [self.tableView reloadData];
    //2.繼續(xù)讀取數(shù)據(jù)(否則只能讀取一次)
    [sock readDataWithTimeout:-1 tag:0];
    
    
}

//客戶端發(fā)送數(shù)據(jù)成功
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    NSLog(@"客戶端發(fā)送數(shù)據(jù)");
    //刷新數(shù)據(jù)
    [self.tableView reloadData];
}



#pragma mark -UITextFieldDelegate  發(fā)送數(shù)據(jù)

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    
    //1.發(fā)送數(shù)據(jù)  具體的數(shù)據(jù)格式會(huì)由硬件工程師定義,示例這里使用冒號(hào):將我的手機(jī)名稱和消息分開(kāi)
    NSString *str = [NSString stringWithFormat:@"%@:%@",[UIDevice currentDevice].name,textField.text];
    
    //2.發(fā)送數(shù)據(jù) 第一個(gè)參數(shù):二進(jìn)制數(shù)據(jù)  第二個(gè)參數(shù):超時(shí)等待  -1為永久等待  tag:消息標(biāo)簽 沒(méi)啥用
    [self.clientSocket writeData:[str dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:1];
    
    //3添加到數(shù)組用于顯示
    [self.tableArr addObject:[str dataUsingEncoding:NSUTF8StringEncoding]];
    
    textField.text = nil;
    
    return YES;
}

1.3-完整代碼及示例演示


#import "ClientViewController.h"

#import "GCDAsyncSocket.h"
#import "WIFITools.h"

@interface ClientViewController ()<GCDAsyncSocketDelegate,UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UILabel *wifiNameLabel;
@property (weak, nonatomic) IBOutlet UILabel *ipAddressLabel;
@property (weak, nonatomic) IBOutlet UIButton *senMsgButton;

@property (weak, nonatomic) IBOutlet UIButton *clientButton;

@property(nonatomic,strong)UITextField *textField;
@property (weak, nonatomic) IBOutlet UITableView *tableView;

//存放客戶端的消息用于顯示
@property(nonatomic,strong)NSMutableArray <NSData *>*tableArr;
//
//客戶端socket
@property(nonatomic,strong)GCDAsyncSocket *clientSocket;
@end

@implementation ClientViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.wifiNameLabel.text = [NSString stringWithFormat:@"wifi名稱:%@",[WIFITools currentWifiSSID]];
    self.ipAddressLabel.text = [NSString stringWithFormat:@"ip地址:%@",[WIFITools localWiFiIPAddress]];
    
    self.tableArr = [NSMutableArray array];
    // Do any additional setup after loading the view.
}



//客戶端開(kāi)始連接
- (IBAction)wifiButtonClik:(UIButton *)sender {
    
    //1.創(chuàng)建客戶端socket
    //在socket通訊中弧哎,無(wú)論是客戶端還是服務(wù)端雁比,任何對(duì)象都是socket,類似于萬(wàn)物皆NSObject
    if (!self.clientSocket) {
        self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    }
    
    
    NSLog(@"%@",self.clientSocket.localHost);
    
    //2.連接服務(wù)端
    //注意:此處有兩個(gè)重點(diǎn)    1.這里的ip地址一定要是同一個(gè)局域網(wǎng)服務(wù)端的ip地址撤嫩,端口號(hào)也要與服務(wù)端連接的端口號(hào)一致   2.實(shí)際開(kāi)發(fā)中偎捎,一般服務(wù)端的ip地址和所監(jiān)聽(tīng)的端口號(hào)都會(huì)在wifit通信協(xié)議中注明,這里只是筆者為了掩飾,所以隨便寫(xiě)了一個(gè)端口號(hào)1234茴她,而這里的ip地址也是筆者為了掩飾給mac電腦設(shè)置了一個(gè)固定ip地址
    [self.clientSocket connectToHost:@"192.168.0.102" onPort:1234 error:nil];
    
    
}



//客戶端發(fā)送數(shù)據(jù)
- (IBAction)sendMsgButton:(UIButton*)sender {
    
    if (!self.textField) {
        self.textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 40)];
        self.textField.delegate = self;
        self.textField.returnKeyType = UIReturnKeySend;
        [self.view addSubview:self.textField];
        
    }
    self.textField.hidden = NO;
    [self.textField becomeFirstResponder];
    
    
}

#pragma mark- GCDAsyncSocketDelegate

//客戶端連接服務(wù)端成功
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
    //1.將開(kāi)始連接按鈕變?yōu)橐堰B接
    [self.clientButton setTitle:@"連接成功" forState:UIControlStateNormal];
    //2.發(fā)送數(shù)據(jù)按鈕開(kāi)啟交互
    self.senMsgButton.enabled = YES;
    
    //3.客戶端開(kāi)始讀取服務(wù)端的數(shù)據(jù)
    [self.clientSocket readDataWithTimeout:-1 tag:0];
}



//客戶端接收數(shù)據(jù)成功
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"客戶端接發(fā)送數(shù)據(jù):%@",str);
    
    //0.添加到數(shù)據(jù)源
    [self.tableArr addObject:data];
    
    //1.刷新界面
    [self.tableView reloadData];
    //2.繼續(xù)讀取數(shù)據(jù)(否則只能讀取一次)
    [sock readDataWithTimeout:-1 tag:0];
    
    
}

//客戶端發(fā)送數(shù)據(jù)成功
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    NSLog(@"客戶端發(fā)送數(shù)據(jù)");
    //刷新數(shù)據(jù)
    [self.tableView reloadData];
}



#pragma mark -UITextFieldDelegate  發(fā)送數(shù)據(jù)

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    
    //1.發(fā)送數(shù)據(jù)  具體的數(shù)據(jù)格式會(huì)由硬件工程師定義蜕径,示例這里使用冒號(hào):將我的手機(jī)名稱和消息分開(kāi)
    NSString *str = [NSString stringWithFormat:@"%@:%@",[UIDevice currentDevice].name,textField.text];
    
    //2.發(fā)送數(shù)據(jù) 第一個(gè)參數(shù):二進(jìn)制數(shù)據(jù)  第二個(gè)參數(shù):超時(shí)等待  -1為永久等待  tag:消息標(biāo)簽 沒(méi)啥用
    [self.clientSocket writeData:[str dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:1];
    
    //3添加到數(shù)組用于顯示
    [self.tableArr addObject:[str dataUsingEncoding:NSUTF8StringEncoding]];
    
    textField.text = nil;
    
    return YES;
}

#pragma mark -UITableViewDelegate

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.tableArr.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"clientCell"];
    
    UILabel *nameLabel = (UILabel *)[cell.contentView viewWithTag:1];
    UILabel *msgLabel = (UILabel *)[cell.contentView viewWithTag:2];
    
    //讀取數(shù)據(jù)
    NSData *data = self.tableArr[indexPath.row];
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSArray *arr = [str componentsSeparatedByString:@":"];
    //顯示數(shù)據(jù)
    nameLabel.text = [NSString stringWithFormat:@"設(shè)備名稱:%@",arr[0]];
    msgLabel.text = [NSString stringWithFormat:@" 數(shù)據(jù):%@",arr[1]];
    
    return cell;
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市败京,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌梦染,老刑警劉巖赡麦,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異帕识,居然都是意外死亡泛粹,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)肮疗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)晶姊,“玉大人,你說(shuō)我怎么就攤上這事伪货∶茄茫” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵碱呼,是天一觀的道長(zhǎng)蒙挑。 經(jīng)常有香客問(wèn)我,道長(zhǎng)愚臀,這世上最難降的妖魔是什么忆蚀? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮姑裂,結(jié)果婚禮上馋袜,老公的妹妹穿的比我還像新娘。我一直安慰自己舶斧,他們只是感情好欣鳖,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著茴厉,像睡著了一般观堂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呀忧,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天师痕,我揣著相機(jī)與錄音,去河邊找鬼而账。 笑死胰坟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播笔横,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼竞滓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了吹缔?” 一聲冷哼從身側(cè)響起商佑,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎厢塘,沒(méi)想到半個(gè)月后茶没,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晚碾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年抓半,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片格嘁。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡笛求,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出糕簿,到底是詐尸還是另有隱情探入,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布懂诗,位于F島的核電站新症,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏响禽。R本人自食惡果不足惜徒爹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芋类。 院中可真熱鬧隆嗅,春花似錦、人聲如沸侯繁。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)贮竟。三九已至丽焊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間咕别,已是汗流浹背技健。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工惰拱, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留雌贱,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像欣孤,于是被迫代替她去往敵國(guó)和親馋没。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理降传,服務(wù)發(fā)現(xiàn)篷朵,斷路器,智...
    卡卡羅2017閱讀 134,601評(píng)論 18 139
  • 名詞延伸 通俗的說(shuō),域名就相當(dāng)于一個(gè)家庭的門(mén)牌號(hào)碼卡乾,別人通過(guò)這個(gè)號(hào)碼可以很容易的找到你翼悴。如果把IP地址比作一間房子...
    楊大蝦閱讀 20,590評(píng)論 2 57
  • Teredo 原理概述 http://www.ipv6bbs.cn/thread-144-1-1.html (出處...
    我是葉問(wèn)小盆友閱讀 1,952評(píng)論 0 1
  • 18.1 引言 TCP是一個(gè)面向連接的協(xié)議。無(wú)論哪一方向另一方發(fā)送數(shù)據(jù)之前幔妨,都必須先在雙方之間建立一條連接鹦赎。本章將...
    張芳濤閱讀 3,344評(píng)論 0 13
  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說(shuō)閱讀 10,869評(píng)論 6 13