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

WIFI通訊客戶端搭建

  • 客戶的職責主要做三件事,一:連接服務端 二:接收來自服務端的數據 三:給服務端發送數據
  • [1.0-準備工作]
  • [1.1-客戶端連接服務端]
  • [1.2-客戶端接收和發送數據到服務端]
  • [1.3-完整代碼及示例演示]

1.0-準備工作

  • 筆者搭建了一個簡單的界面,主要功能就是客戶端連接服務端監聽的網絡,連接成功之后可以給服務端發送數據

1.1-客戶端連接服務端

  • 1.創建客戶端Socket
  • 2.客戶端連接服務端socket
    • socket本質就是ip地址加端口號,所以客戶端連接的也是ip地址加端口號,只不過這一個ip地址是服務端在局域網中的ip地址(上一小節獲?。?,端口號也是服務端所監聽的端口號(如果與服務端的ip地址和監聽的端口號不一致,客戶端是無法連接的,因為這一個i地址的電腦的端口號沒有被監聽)

//客戶端開始連接
- (IBAction)wifiButtonClik:(UIButton *)sender {
    
    //1.創建客戶端socket
    //在socket通訊中,無論是客戶端還是服務端,任何對象都是socket,類似于萬物皆NSObject
    if (!self.clientSocket) {
        self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    }
    
    
    NSLog(@"%@",self.clientSocket.localHost);
    
    //2.連接服務端
    //注意:此處有兩個重點    1.這里的ip地址一定要是同一個局域網服務端的ip地址,端口號也要與服務端連接的端口號一致   2.實際開發中,一般服務端的ip地址和所監聽的端口號都會在wifit通信協議中注明,這里只是筆者為了掩飾,所以隨便寫了一個端口號1234,而這里的ip地址也是筆者為了掩飾給mac電腦設置了一個固定ip地址
    [self.clientSocket connectToHost:@"192.168.0.102" onPort:1234 error:nil];
    
    
}

1.2-客戶端接收和發送數據到服務端

  • ***1.客戶端連接成功之后,開始讀取服務端的數據

  • 2.客戶端將接收到服務端的數據添加在數組,用于顯示(實際開發中可能需要處理其他邏輯,具體看需求)

  • 3.客戶端發送數據到服務端(實際開發中數據格式由硬件工程師來定義)


#pragma mark- GCDAsyncSocketDelegate

//客戶端連接服務端成功
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
    //1.將開始連接按鈕變為已連接
    [self.clientButton setTitle:@"連接成功" forState:UIControlStateNormal];
    //2.發送數據按鈕開啟交互
    self.senMsgButton.enabled = YES;
    
    //3.客戶端開始讀取服務端的數據
    [self.clientSocket readDataWithTimeout:-1 tag:0];
}



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

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



#pragma mark -UITextFieldDelegate  發送數據

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    
    //1.發送數據  具體的數據格式會由硬件工程師定義,示例這里使用冒號:將我的手機名稱和消息分開
    NSString *str = [NSString stringWithFormat:@"%@:%@",[UIDevice currentDevice].name,textField.text];
    
    //2.發送數據 第一個參數:二進制數據  第二個參數:超時等待  -1為永久等待  tag:消息標簽 沒啥用
    [self.clientSocket writeData:[str dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:1];
    
    //3添加到數組用于顯示
    [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.
}



//客戶端開始連接
- (IBAction)wifiButtonClik:(UIButton *)sender {
    
    //1.創建客戶端socket
    //在socket通訊中,無論是客戶端還是服務端,任何對象都是socket,類似于萬物皆NSObject
    if (!self.clientSocket) {
        self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    }
    
    
    NSLog(@"%@",self.clientSocket.localHost);
    
    //2.連接服務端
    //注意:此處有兩個重點    1.這里的ip地址一定要是同一個局域網服務端的ip地址,端口號也要與服務端連接的端口號一致   2.實際開發中,一般服務端的ip地址和所監聽的端口號都會在wifit通信協議中注明,這里只是筆者為了掩飾,所以隨便寫了一個端口號1234,而這里的ip地址也是筆者為了掩飾給mac電腦設置了一個固定ip地址
    [self.clientSocket connectToHost:@"192.168.0.102" onPort:1234 error:nil];
    
    
}



//客戶端發送數據
- (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

//客戶端連接服務端成功
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
    //1.將開始連接按鈕變為已連接
    [self.clientButton setTitle:@"連接成功" forState:UIControlStateNormal];
    //2.發送數據按鈕開啟交互
    self.senMsgButton.enabled = YES;
    
    //3.客戶端開始讀取服務端的數據
    [self.clientSocket readDataWithTimeout:-1 tag:0];
}



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

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



#pragma mark -UITextFieldDelegate  發送數據

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    
    //1.發送數據  具體的數據格式會由硬件工程師定義,示例這里使用冒號:將我的手機名稱和消息分開
    NSString *str = [NSString stringWithFormat:@"%@:%@",[UIDevice currentDevice].name,textField.text];
    
    //2.發送數據 第一個參數:二進制數據  第二個參數:超時等待  -1為永久等待  tag:消息標簽 沒啥用
    [self.clientSocket writeData:[str dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:1];
    
    //3添加到數組用于顯示
    [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];
    
    //讀取數據
    NSData *data = self.tableArr[indexPath.row];
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSArray *arr = [str componentsSeparatedByString:@":"];
    //顯示數據
    nameLabel.text = [NSString stringWithFormat:@"設備名稱:%@",arr[0]];
    msgLabel.text = [NSString stringWithFormat:@" 數據:%@",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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容