如何使用AsyncSocket编写一个非常小型的群聊系统

本人刚刚从事ios开发半年, 前几天想了解一下苹果的Socket编程, 然后去百度东西, 发现许多人都是建议使用AsyncSocket, 然后就去了解了一下, 现在我把我的学习经验总结一下, 哪里说的不对还望赐教。 

想学习Socket,先去了解一下TCP和UDP,原理的东西还是自己去百度吧。

在ios中使用Socket可以使用封装好的AsyncSocket库, 用来简化对CFNetwork的调用。你需要从网上下载AsyncSocket 库, 里面一共有四个文件, 全部拖到工程中,如果你的程序是ARC的,需要改一下 -fno-objc-arc

我先说明我的程序的功能,这样你就很容易看懂了,我在页面上放了一个大大的UITextField,用来接受从服务器返回来的数据,下面是一个UITextField,用来输入内容,最下面是三个按钮-连接-发送-断开连接

现在我开始贴代码了,代码可能看着不明朗, 我把xcode截图可以看图片

客户端:

//

//  RootViewController.m

//  SocketTest

//

//  Created by mac on 15/1/29.

//  Copyright (c) 2015 MAC. All rights reserved.

//


#import "RootViewController.h"

#import "AsyncSocket.h"

#define Ksize     self.view.bounds.size

@interface RootViewController ()<UITextFieldDelegate>

{

    AsyncSocket* socketTest;

    UITextField* SendText;

    UITextView* historyLabel;

    NSMutableString* historyStr;

}

@end


@implementation RootViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    historyStr=[[NSMutableString alloc]init];

//    [self connAction];

    

    historyLabel=[[UITextView alloc]initWithFrame:CGRectMake(20, 64, Ksize.width-40, Ksize.height-150-64)];

    historyLabel.userInteractionEnabled=NO;

    [historyLabel setBackgroundColor:[UIColor grayColor]];

    [self.view addSubview:historyLabel];

    

    

    SendText=[[UITextField alloc]initWithFrame:CGRectMake(20, Ksize.height-110, Ksize.width-40, 40)];

    [SendText setBackgroundColor:[UIColor grayColor]];

    SendText.delegate=self;

    [self.view addSubview:SendText];

    UIButton* connectBtn=[UIButton buttonWithType:UIButtonTypeSystem];

    [connectBtn setFrame:CGRectMake(20, Ksize.height-50, 100, 50)];

    [connectBtn setTitle:@"连接" forState:UIControlStateNormal];

    [connectBtn addTarget:self action:@selector(connAction) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:connectBtn];

    

    UIButton* btn1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];

    [btn1 setTitle:@"发送" forState:UIControlStateNormal];

    [btn1 setFrame:CGRectMake(CGRectGetMaxX(connectBtn.frame), Ksize.height-50, 50, 50)];

    [btn1 addTarget:self action:@selector(sendAction:) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:btn1];

    

    UIButton* disconnBtn=[UIButton buttonWithType:UIButtonTypeSystem];

    [disconnBtn setTitle:@"断开连接" forState:UIControlStateNormal];

    [disconnBtn setFrame:CGRectMake(CGRectGetMaxX(btn1.frame), Ksize.height-50, 150, 50)];

    [disconnBtn addTarget:self action:@selector(disconnectAction) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:disconnBtn];

}

-(void)disconnectAction{

    //断开已有的连接

    [socketTest disconnect];


}

-(BOOL)textFieldShouldReturn:(UITextField *)textField{

    [textField resignFirstResponder];

    return  YES;

}

//连接到指定的服务器

-(void)connAction

{

    if (!socketTest) {

        //初始化并设置代理  需要遵守协议AsyncSocketDelegate

        socketTest = [[AsyncSocket alloc]initWithDelegate:self];

        

    }

    //如果已经连接到指定服务器

    if ([socketTest isConnected]) {

        //断开已有的连接

        [socketTest disconnect];

    }

    //clientSocket  ,连接到指定的服务器(服务器有固定的ip地址和端口)

    //  固定的写法,自己本机的ip地址

    [socketTest connectToHost:@"192.168.1.115" onPort:5678 error:Nil];


}

#pragma mark- async aocket delegate

//与指定服务器连接后,出触发这个方法

-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port

{

    NSLog(@"与服务器:%@ %d 发起连接",host,port);

   

    [socketTest readDataWithTimeout: -1 tag: 10];


}

//向服务端发送消息

-(void)sendAction:(UIButton*)sender

{

    [historyStr appendString:[NSString stringWithFormat:@"%@\n",SendText.text]];

    //转换成data

    NSData* data=[[NSString stringWithFormat:@"%@",SendText.text] dataUsingEncoding:NSUTF8StringEncoding];

    //向指定服务器发送消息

    //timeout代表无限时的发送

    //tag对当前操作的标记

    [socketTest writeData:data withTimeout:-1 tag:0];

    SendText.text=@"";

}

//消息发送完毕,出发的方法

-(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag

{

    NSLog(@"send!");

}


//读取服务器的数据

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag

{

    NSString *msg = [[NSString alloc] initWithData: data encoding:NSUTF8StringEncoding];


    NSString* history= [NSString stringWithFormat:@"%@\n",msg];

    historyLabel.text=history;

    [socketTest readDataWithTimeout: -1 tag: 10];


}

- (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


下来是服务器端的代码

先给你说说怎么用xcode创建一个mac工程,选中我标记的那个就行了

然后将AsyncSocket的四个文件导入进去

开始贴代码了

//新建工程,建的该工程

#import <Cocoa/Cocoa.h>//cocoa 是苹果封装的mac软件开发的框架,ios开发的框架叫CocoaTouch

#import "AsyncSocket.h"

@interface DCAppDelegate : NSObject <NSApplicationDelegate,AsyncSocketDelegate>

@property (assign) IBOutlet NSWindow *window;


@end

//

//  DCAppDelegate.m

//  TCPServer

//

//  Created by qianfeng on 14-9-22.

//  Copyright (c) 2014 MAC. All rights reserved.

//


#import "DCAppDelegate.h"


@implementation DCAppDelegate{

    AsyncSocket* _serverSocket;//用于监听指定的ip和端口,看是否客户端连入

    NSMutableArray* _scoketArray;//用于存放与客户端交互的socket对象

    NSMutableString* postString;

}


- (void)applicationDidFinishLaunching:(NSNotification *)aNotification

{

    // Insert code here to initialize your application

    _scoketArray=[[NSMutableArray alloc]init];

    postString=[[NSMutableString alloc]init];

    //0.2秒之后,self调用createServer方法

    [self performSelector:@selector(createServer) withObject:Nil afterDelay:0.2];

}

-(void)createServer{

    //初始化设置代理

    _serverSocket=[[AsyncSocket alloc]initWithDelegate:self];

    //负责监听指定的ip和端口,看是否有客户端接入

    _serverSocket.delegate=self;

    

    //ip可以不写

    [_serverSocket acceptOnPort:5678 error:Nil];

}


#pragma mark  async delegate

//当服务端收到客户端的链接是,出发此方法

//newSocket  服务端自动创建的新的socket对象,用于处理与链接的客户端的交互

-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket

{

    NSLog(@"accept!");

    NSLog(@"IP:%@",[newSocket connectedHost]);

    //添加到数组中维护

    [_scoketArray addObject:newSocket];

    

    //-1  不限时的监听

    [newSocket readDataWithTimeout:-1 tag:0];

}

//服务端收到客户端的消息后,出发此方法

-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag

{

    //data 客户端发送过来的消息

    NSString* str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

    [postString appendString:[NSString stringWithFormat:@"%@:%@\n",[sock connectedHost],str]];


    //sock继续监听客户端是否发来消息

    [sock readDataWithTimeout:-1 tag:2];

   

    //向客户端发送消息

    NSData* postData=[postString dataUsingEncoding:NSUTF8StringEncoding];

    for (AsyncSocket* clientSocket in _scoketArray) {

        

        [clientSocket writeData:postData withTimeout:-1 tag:10];

    }

}

//消息发送完毕,出发的方法


- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag{

    NSLog(@"message did write");

    [_serverSocket readDataWithTimeout:-1 tag:1];

}



//如果客户端关闭,或者长期处于不活跃的状态,就会断开与服务端的链接

-(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err{

    NSLog(@"即将断开");

}

//客户端已经断开链接

-(void)onSocketDidDisconnect:(AsyncSocket *)sock

{

    NSLog(@"已经断开");

}

@end


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值