Socket编程 --- TCP

Socket编程  --- TCP

TCP socket 原理 :

demo:效果图

Socket编程  --- UDP 

本例子使用AsyncSocket 第三方开源库

首先 、导入处理网络数据的库 : ,导入方式如图

1_在.h文件中导入 头文件 

#import "AsyncSocket.h"

2_创建两个AsyncSocket类对象,一个作为接收方(服务端)、一个作为发送方(客户端)、和NSMutableArray对象用于接收客户端发送过来的数据。

@interface ViewController : UIViewController<AsyncSocketDelegate>
{
    //服务端
    AsyncSocket *recvSocket;
    // 客户端
    AsyncSocket *sendSocket;
    // 
    NSMutableArray *recvArr;
    // 判断客户端是否连接到了服务端
    BOOL isLink;
}
 

3_界面设置 两个UITextField  一个 UITextView 、一个UIButton 按钮事件,并在xib 中创建相应的控件,相关操作如图所示

@property (retain, nonatomic) IBOutlet UITextField *ipField;
@property (retain, nonatomic) IBOutlet UITextField *sendField;
@property (retain, nonatomic) IBOutlet UITextView *contentView;

- (IBAction)sendText:(id)sender;

二— 切换到 .m 实现文件

1_@synthesize 刚创建的@property 属性 

@synthesize ipField;
@synthesize sendField;
@synthesize contentView;

在  方法中将view 上的对象置为空 。

- (void)viewDidUnload
{
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    [self setIpField:nil];
    [self setSendField:nil];
    [self setContentView:nil];
    [super viewDidUnload];
    
}

中将view 上的对象release 掉

- (void)dealloc {
    [ipField release];
    [sendField release];
    [contentView release];
    [super dealloc];
}

  1—在 方法中实例化创建的两个AsyncSocket 类对象。和用于接收客户端数据的可变数组

调用 initWithDelegate 初始化,并在.h文件中引入代理

// 记得初始化数组
    recvArr = [[NSMutableArray alloc]initWithCapacity:0];
    
    // 服务端  
    recvSocket = [[AsyncSocket alloc]initWithDelegate:self];
    
    // 客户端
    sendSocket = [[AsyncSocket alloc]initWithDelegate:self];

设置服务端(recvSocket)的接收端口号  调用方法 : acceptOnPort:error: (端口号 > 5000 为妙)

 // 服务端开始等待别的客户端的链接
    //  端口为 > 5000  较合适 : 65535  
    [recvSocket acceptOnPort:5678 error:nil];

这个时候服务端(recvSocket) 就准备就绪,预留了一条通道让客户端连接并发送数据。首先,客户端必须先取得入口的通行证,才能向服务端发送数据。(客户端发送数据还需经过服务端的许可,只有服务端许可才可以发送数据)。

客户端: 当点击发送的时候就触发连接 、sendSocket 调用 connectToHost:onPort:withTimeout:error:方法连接到服务端。host填的是服务端的ip地址。port 填的是端口(即服务端预留的通道)

当创建连接时,成功连接将调用 onSocket:didConnectToHost:port:方法,证明连接成功

//调用这个方法的时候,就证明链接成功
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{
    isLink = YES;
}

当连接成功的时候:::::

1——服务端就等待客户端发送数据 调用onSocket:didAcceptNewSocket:

// 调用这个方法证明接受到了一个链接
- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
{
    //newSocket 就为新的链接
    // 客户端和服务器链接 : 将请求保存 (表示同意链接,相当于对newSocket 做了个retain操作)
    [recvArr addObject:newSocket];
// 等待客户端发送数据 [newSocket readDataWithTimeout:-1 tag:100]; //什么时候读取到了数据 }

2——客户端就可以向服务端发送数据了。。。发送的数据要转为NSData格式 

客户端(sendSocket)调用writeData:withTimeout:tag: 方法发送数据

- (IBAction)sendText:(id)sender {

    // 如果没链接,那么去链接服务端
    if (sendSocket.isConnected == NO) {
        // TCP_Socket 的端口当链接过后就释放掉,将不再占用端口
        [sendSocket connectToHost:ipField.text onPort:5678 withTimeout:60 error:nil];
        //什么时候链接成功 
    }
    
    // NSString -> NSData 
    if (isLink == YES) {
        NSData *data = [sendField.text dataUsingEncoding:NSUTF8StringEncoding];
        // 发送数据
        [sendSocket writeData:data withTimeout:60 tag:100];
        // 什么时候知道数据发送出去(发送成功)
    }
    
} 

当调用onSocket:didWriteDataWithTag:方法则表示调用数据成功。

// 调用这个方法表示数据发送成功
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    if (tag == 100) NSLog(@"yes");
    else NSLog(@"no");
}

那么服务端什么时候接收到了数据?

onSocket:didReadData:withTag:就表示服务端接收到了用户数据  

此时应该继续调用 readDataWithTimeout:tag: 方法一直接收客户端发送过来的数据。

// 调用这个方法就证明接受到了客户端发送的数据
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    contentView.text = [NSString stringWithFormat:@"%@\n对方说:%@",contentView.text,str];
    //继续监听 :(继续等待服务端发送数据)
    [sock readDataWithTimeout:-1 tag:100];
    
}

 

the end !

thx。。

 

 

 

 

 

 

posted @ 2013-01-31 14:36  Jere-Jobs  阅读(512)  评论(0编辑  收藏  举报