即時通訊:socket 使用,即時通訊socket

來源:互聯網
上載者:User

即時通訊:socket 使用,即時通訊socket

   上篇說到即時通訊編程選擇哪種方式,筆者用socket編寫了一個仿QQ聊天的通訊應用,順便就用這個應用介紹一個socket的使用吧

   socket與XMPP差別之處就是socket的用戶端與伺服器端都需要自己來搭建。XMPP 有現成的伺服器跟用戶端,編寫測試起來就比較輕鬆,所以,XMPP也就成了即時通訊編程的主流了。不過介於個人興趣,socket還是值得探究的。

  好了,就說這麼多。下面就是筆者的socket應用。

  首先先介紹一下用戶端這是用戶端登陸介面


接下來,進行註冊操作

點擊註冊--(向伺服器端發送註冊訊息---下面代碼會介紹

用戶端註冊的使用者資訊儲存在伺服器端的資料庫

輸入剛剛註冊的使用者名稱,密碼登陸


登陸頁面代碼   記得先匯入 AsyncSocket  架構

#import <UIKit/UIKit.h>#import "AsyncSocket.h"typedef void(^isSuccessBlock)(BOOL);@interface ViewController : UIViewController{        __weak IBOutlet UIView *_contBgView;  //登陸視圖    __weak IBOutlet UITextField *_usernameField;    __weak IBOutlet UITextField *_pwdField;    __weak IBOutlet UITableView *_tableView;    __weak IBOutlet UIView *_sendView;    //資訊文本    __weak IBOutlet UITextField *_message;}@property(nonatomic,strong)AsyncSocket *socket; //用戶端通訊對象@property(nonatomic,copy)isSuccessBlock block;  //登陸成功驗證Block//發送訊息- (IBAction)sendMessage:(UIButton *)sender;//驗證使用者- (IBAction)contentAction:(UIButton *)sender;//註冊使用者- (IBAction)registerAction:(UIButton *)sender;@end

#import "ViewController.h"#import "MyCell.h"#import "registerViewController.h"@interface ViewController ()<UITableViewDataSource,UITableViewDelegate,AsyncSocketDelegate>//設定通訊代理{    NSMutableArray *dataArr; //存放本用戶端及其它用戶端訊息    NSString *username;      //驗證通過後的使用者名稱}@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];        self.title=@"Cheep";        _contBgView.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:@"red.jpg"]];    dataArr=[NSMutableArray array];    _tableView.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:@"chat_bg_default.jpg"]];    _tableView.separatorStyle=UITableViewCellSeparatorStyleNone;    _tableView.rowHeight=64;    _sendView.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:@"chat_bottom_textfield.png"]];    //ios socket第三方架構 AsyncSocket使用簡介,串連,心跳,斷線,資料發送與接收    /*    1. socket 串連    2. socket 中斷連線與重連    3. socket 發送與接收資料    4. 簡單使用說明    */       if (_socket == nil) {                _socket=[[AsyncSocket alloc] initWithDelegate:self];        //設定好的伺服器位址跟連接埠        [_socket connectToHost:@"192.168.7.19" onPort:6225 error:nil];    }        }//驗證使用者- (IBAction)contentAction:(UIButton *)sender {        /*   key  :  value             doWhat:  commit(驗證標記)      username:  _usernameField.text             ...     */    //將字串轉成字典樣式封裝發送    NSString *dataStr= [NSString stringWithFormat:@"{\"doWhat\":\"commit\",\"username\":\"%@\",\"password\":\"%@\"}",_usernameField.text,_pwdField.text];    NSData *data=[dataStr dataUsingEncoding:NSUTF8StringEncoding];    /*     data 向伺服器發送的資料     -1   請求逾時時間 -1為一直等待伺服器回複     tag  是為了在回調方法中匹配發起調用的方法的,不會加在傳輸資料中     */    [_socket writeData:data withTimeout:-1 tag:0];    //監聽請求訊息    [_socket readDataWithTimeout:-1 tag:0];        //伺服器返回驗證訊息    _block=^(BOOL result)    {        if (!result) {            _usernameField.text=@"";            _pwdField.text=@"";        }else        {            //成功----記錄下使用者名稱            username=_usernameField.text;            _contBgView.hidden=YES; //登陸頁面隱藏            //訊息頁面顯示            _tableView.hidden=NO;            _sendView.hidden=NO;        }    }; }//註冊使用者- (IBAction)registerAction:(UIButton *)sender {        //註冊頁面控制器    registerViewController *Ctrl=[[registerViewController alloc] init];        [self presentViewController:Ctrl animated:YES completion:^{        ;    }];        //block回調(拿到註冊頁面,使用者名稱,密碼)    Ctrl.myBlock=^(NSString *textNum,NSString *textPassWord)    {                // resiger - 註冊商標符號        NSString *dataStr= [NSString stringWithFormat:@"{\"doWhat\":\"resiger\",\"username\":\"%@\",\"password\":\"%@\"}",textNum,textPassWord];        NSData *data=[dataStr dataUsingEncoding:NSUTF8StringEncoding];        //向伺服器發送註冊請求,並監聽請求資訊        [_socket writeData:data withTimeout:-1 tag:0];        [_socket readDataWithTimeout:-1 tag:0];            };        }//向伺服器發送訊息- (IBAction)sendMessage:(UIButton *)sender {            if(_message.text.length >0)    {        //顯示在本用戶端UI的訊息        NSDictionary *dic=[NSDictionary dictionary];        dic=@{              @"socket":@"client",              @"username":username,              @"message":_message.text              };        [dataArr addObject:dic];        //插入資料到最後一個儲存格        NSIndexPath *index=[NSIndexPath indexPathForRow:dataArr.count-1 inSection:0];        [_tableView insertRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationFade];        //滾動到最後一個儲存格        [_tableView scrollToRowAtIndexPath:index atScrollPosition:UITableViewScrollPositionBottom animated:YES];                /*         (內容包括 :內容標記,本用戶端使用者名稱,是否是用戶端,發送的內容)當然自己可以定製,只要在伺服器端也做相應的接收就可以         */                NSString *message= [NSString stringWithFormat:@"{\"doWhat\":\"message\",\"username\":\"%@\",\"socket\":\"client\",\"message\":\"%@\"}",username,_message.text];        NSData *data=[message dataUsingEncoding:NSUTF8StringEncoding];        //向伺服器發送聊天訊息        [_socket writeData:data withTimeout:-1 tag:0];        [_socket readDataWithTimeout:-1 tag:0];        _message.text=@"";    }}#pragma mark- UITableView dataSource delegate- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{    return dataArr.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    static NSString *intenty = @"UITableViewCell";        MyCell*cell = [tableView dequeueReusableCellWithIdentifier:intenty];     if (cell == nil) {                cell=[[[NSBundle mainBundle] loadNibNamed:@"MyCell" owner:self options:nil] lastObject];    }    NSDictionary *message =dataArr[indexPath.row];    //將model交給視圖去顯示    cell.message=message;    return cell;}#pragma mark - AsyncSocketDelegate//1.用戶端串連伺服器調用的協議方法- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{    //監聽服務端socket訊息    [sock readDataWithTimeout:-1 tag:0];    }//2.接受伺服器發送過來的資料(讀取資料)- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{    //伺服器處理用戶端發送的訊息,相應的返回用戶端能識別的訊息(比如,上面用戶端向伺服器發送字典訊息,伺服器也返回相應的字典訊息)    NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];//    NSLog(@"%@",dic);    NSString *dowhat=[dic objectForKey:@"doWhat"]; //內容標記    NSString *type=[dic objectForKey:@"type"];    //處理結果        if ([dowhat isEqualToString:@"commit"]) //登陸驗證返回訊息    {        if ([type integerValue]==1) {            NSLog(@"驗證成功");            _block(YES);        }else        {            NSLog(@"驗證失敗");        }    }else if ([dowhat isEqualToString:@"resiger"]) //註冊返回訊息    {        if ([type integerValue]==2) {                        NSLog(@"註冊成功");                    }else        {                 }            }else if([dowhat isEqualToString:@"message"]) //聊天訊息返回的訊息    {        //拿到其他用戶端發送的訊息,        NSString *message=[dic objectForKey:@"message"];        NSString *fromusername=[dic objectForKey:@"username"];//        NSString *socket=[dic objectForKey:@"socket"];        dic=@{              @"socket":@"server",              @"username":fromusername,              @"message":message              };        [dataArr addObject:dic];                //UI操作放在主線程上        dispatch_async(dispatch_get_main_queue(), ^{            //插入資料到最後一個儲存格            NSIndexPath *index=[NSIndexPath indexPathForRow:dataArr.count-1 inSection:0];            [_tableView insertRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationFade];            //滾動到最後一個儲存格            [_tableView scrollToRowAtIndexPath:index atScrollPosition:UITableViewScrollPositionBottom animated:YES];        });                    }    //繼續監聽伺服器發來的訊息    [sock readDataWithTimeout:-1 tag:0];}@end

註冊頁面在視圖返回登陸頁面的時候記得使用Block回調即可

    //調用--先判斷    if (self.myBlock != nil) {                self.myBlock(_fieldNum.text,_fieldPassWord.text);    }
    //布局子視圖 需判斷訊息是否為自己發送    if ([what isEqualToString:@"client"]) {                _iconImage.frame = CGRectMake(Kw - 50, 10, 40, 40);        _bgImage.frame = CGRectMake(Kw-50-(size.width + 30)-10, 10, size.width + 30, size.height + 30);        _contText.frame = CGRectMake(Kw-50-size.width-30, 20, size.width, size.height);         _usernameLabel.frame=CGRectMake(Kw-70, 1, 100, 17);            }else if([what isEqualToString:@"server"])    {                _iconImage.frame = CGRectMake(10, 10, 40, 40);        _bgImage.frame = CGRectMake(60, 10, size.width + 30, size.height + 30);        _contText.frame = CGRectMake(80, 20, size.width, size.height);        _usernameLabel.frame=CGRectMake(52, 1, 100, 17);    }
單元格布局根據字典內的訊息的出處,判斷該怎麼布局。

socket 用戶端器就介紹到這裡。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.