Socket通信(一)

//
//  ViewController.m
//  Socket1
//
//  Created by 阿仁欧巴 on 16/5/7.
//  Copyright © 2016年 aren. All rights reserved.
//

#import "ViewController.h"

@interface ViewController () <NSStreamDelegate, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate>
{
    NSInputStream *_inputStream;
    NSOutputStream *_outStream;
}
//@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomViewConstraint;
@property (weak, nonatomic) IBOutlet UIView *commentView;//发送消息的文本框的父视图,根据键盘的出现与否设置它的frame
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *chatMsgs; //聊天消息数组

@end

@implementation ViewController

- (NSMutableArray *)chatMsgs
{
    if (!_chatMsgs) {
        _chatMsgs = [NSMutableArray array];
    }
    return _chatMsgs;
}

//连接服务器的按钮
- (IBAction)connect:(id)sender
{
    //1.获取服务器的IP地址和端口号
    NSString *host = @"127.0.0.1";
    int port = 8080;

    //2.获取输入输出流
    CFReadStreamRef readRef;
    CFWriteStreamRef writeRef;

    //3.将C语言对象转换成OC对象
    _inputStream = (__bridge NSInputStream *)(readRef);
    _outStream = (__bridge NSOutputStream *)(writeRef);

    //4.建立连接
    CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readRef, &writeRef);

    //5.设置代理
    _inputStream.delegate = self;
    _outStream.delegate = self;
#pragma mark ---如果不添加到主循环,代理方法可能不执行----
    //6.扔进主循环
    [_inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    [_outStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

    //7.打开输入输出流
    [_inputStream open];
    [_outStream open];
#pragma mark ---链接结束时,需要将输入输出流从主循环中移除 并且关闭输入输出流, 在代理方法中执行----

}

//登录按钮
- (IBAction)login:(id)sender
{
    //登陆的指令
    NSString *loginString = @"iam:arenouba";
    //转换成NSData类型的
    NSData *data = [loginString dataUsingEncoding:NSUTF8StringEncoding];
    //输出流发送登录数据给服务器
    [_outStream write:data.bytes maxLength:data.length];

}

#pragma mark ---输入流 读取 服务器 返回的数据  XMPP 已经封装好了,不用我们处理---
- (void)readData
{
    //建立一个缓冲区,可以放1024个字节
    uint8_t buf[1024];
    // len 返回实际存放的字节数
    NSInteger len = [_inputStream read:buf maxLength:sizeof(buf)]; //sizeof(buf)
    //把字节转化成字符串
    NSData *data = [NSData dataWithBytes:buf length:len];
    //转换成字符串 从服务器接收到的数据
    NSString *recieveString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    //刷新数据
    [self reloadDataWithText:recieveString];

    NSLog(@"%@",recieveString);
}

#pragma mark --- 点击发送按钮时 获取文本输入框的文字,并刷新tableView ---

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    NSString *text = textField.text;
    NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding];
    [self reloadDataWithText:text];
    //发送数据给服务器
    [_outStream write:data.bytes maxLength:data.length];
    //发送完成后,清空文本框
    textField.text = nil;
    return YES;
}

- (void)reloadDataWithText:(NSString *)text
{
    //添加文本输入框的数据到消息数组中
    [self.chatMsgs addObject:text];
    //刷新
    [self.tableView reloadData];
    //发送一条消息,使tableView跟着向上滚动一行
    NSIndexPath *lastIndexPath = [NSIndexPath indexPathForRow:self.chatMsgs.count - 1 inSection:0];
    [self.tableView scrollToRowAtIndexPath:lastIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

}

#pragma mark --- 将要拖动时,键盘消失---

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}

#pragma mark ----NSStreamDelegate -----

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
#warning mark --- 这是在主线程中执行的
    NSLog(@"%@",[NSThread currentThread]);
    /*
     NSStreamEventNone = 0,
     NSStreamEventOpenCompleted = 1UL << 0, 输入输出流打开完成
     NSStreamEventHasBytesAvailable = 1UL << 1, 有字节可读
     NSStreamEventHasSpaceAvailable = 1UL << 2, 可以发送字节
     NSStreamEventErrorOccurred = 1UL << 3, 连接出现了错误
     NSStreamEventEndEncountered = 1UL << 4 连接结束
     */

    switch (eventCode) {
        case NSStreamEventOpenCompleted:
            NSLog(@" 输入输出流打开完成");
            break;
        case NSStreamEventHasBytesAvailable:
            NSLog(@"有字节可读");
            break;
        case NSStreamEventHasSpaceAvailable:
            NSLog(@"可以发送字节");
            break;
        case NSStreamEventErrorOccurred:
            NSLog(@"连接错误");
            break;
        case NSStreamEventEndEncountered:
            NSLog(@"连接结束");
            //关闭输入输出流
            [_inputStream close];
            [_outStream close];

            //从主循环移除
            [_inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
            [_outStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

            break;
        default:
            break;
    }

}

- (void)viewDidLoad {
    [super viewDidLoad];

    //监听键盘将要出现时
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChang:) name:UIKeyboardWillChangeFrameNotification object:nil];
    //监听键盘将要隐藏时
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHidden:) name:UIKeyboardWillHideNotification object:nil];

    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    [self.view insertSubview:_tableView atIndex:0];

    // Do any additional setup after loading the view, typically from a nib.
}

- (void)keyboardWillChang:(NSNotification *)noti
{
    NSLog(@"%@",noti.userInfo);
    //键盘结束的y值
    CGRect kbEndFrame = [noti.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    [UIView animateWithDuration:[noti.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue] animations:^{
        self.commentView.transform = CGAffineTransformMakeTranslation(0, -kbEndFrame.size.height);
    }];

}

- (void)keyboardWillHidden:(NSNotification *)noti
{
    //键盘结束的y值
    [UIView animateWithDuration:[noti.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue] animations:^{
        self.commentView.transform = CGAffineTransformIdentity;
    }];

}

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

  if (cell == nil) {

cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];

}

  cell.textLabel.text = self.chatMsgs[indexPath.row];
    return cell;
}

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

@end
时间: 2024-10-14 10:47:58

Socket通信(一)的相关文章

TCP及socket通信原理

一.网络互联模型 因特网在刚面世时,只有同一制造商生产的计算机才能彼此通信,制定网络互联模型的目的就是为异种的计算机互连提供一个共同的基础和标准框架,并为保持相关标准的一致性和兼容性提供共同的参考. 互联参考模型: OSI七层模型(Open System Interconnect):应用层.表示层.会话层.传输层.网络层.数据链路层.物理层 DoD四层模型:是OSI七层模型的浓缩版,包括 进程/应用层.主机到主机层.因特网层.网络接入层 以上两种模型是层次型的,分层模型的优点主要在于: ①将网络

java socket通信-传输文件图片--传输图片

ClientTcpSend.java   客户端发送类 package com.yjf.test; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.net.InetSocketAddress; import java.net.Socket; public class ClientTcpSend { public static String clien

c# socket通信较完善方案

c#的socket通信应用.文件较多.附件为工程.  core AbstractBytesWorker.cs    字节工作器(基类),用于用于同一不同功能的字节工作器 BinaryHand.cs  2进制处理器.  ThDispose.cs 处理回收相关 crc  entity ThPersonInfo.cs manager ThSocketManager.cs  ThSocketManagerBusiness.cs 所有的业务 request RequestCode.cs  请求码 ThPr

深入浅出讲解:php的socket通信

深入浅出讲解:php的socket通信 对TCP/IP.UDP.Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵.那么我想问: 1.         什么是TCP/IP.UDP?2.         Socket在哪里呢?3.         Socket是什么呢?4.         你会使用它们吗? 什么是TCP/IP.UDP? TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协

Android简单Socket通信demo

一.Android Socket 通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据.而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求. 那么,什么是socket?Socket又称套接字,在程序内部提供了与外界通信的端口,即端口通信

php的socket通信

对TCP/IP.UDP.Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵.那么我想问: 1.         什么是TCP/IP.UDP?2.         Socket在哪里呢?3.         Socket是什么呢?4.         你会使用它们吗? 什么是TCP/IP.UDP? TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网

Socket通信(转)

一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据.而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求. 那么,什么是socket?Socket又称套接字,在程序内部提供了与外界通信的端口,即端口通信.通过建立sock

基于Java NIO的Socket通信

Java NIO模式的Socket通信,是一种同步非阻塞IO设计模式,它为Reactor模式实现提供了基础. 下面看看,Java实现的一个服务端和客户端通信的例子. NIO模式的基本原理描述如下: 服务端打开一个通道(ServerSocketChannel),并向通道中注册一个选择器(Selector),这个选择器是与一些感兴趣的操作的标识(SelectionKey,即通过这个标识可以定位到具体的操作,从而进行响应的处理)相关联的,然后基于选择器(Selector)轮询通道(ServerSock

Socket通信

1:ServerSocket. 构造方法:ServerSocket(int port) : 创建一个绑定端口号的服务器 accept();监听并且接受Socket,并且返回一个Socket通信包. 2:Socket. 构造方法:Socket(String host,int port); 字节流: getOutputStream(); 输出流方法 (outputStream类) getInputStream();输入流方法 字符流: PrintWriter pw = new printWriter

VS下使用Google Protobuf完成SOCKET通信

如何在Windows环境下的VS中安装使用Google Protobuf完成SOCKET通信 出处:如何在Windows环境下的VS中安装使用Google Protobuf完成SOCKET通信 最近一段时间,由于项目的需要,接触到了Protobuf这个东东,在Linux环境下,体验了一把,感觉挺不错,很方便,且高效.是一个非常值得学习掌握和应用的数据抽象.平台无关.功能强大.…(此处省略1000字)的开源工具. Google虽然把Protobuf做成了跨平台.跨语言,但作为微软的死对头,它在re