//
// ViewController.m
// socket
//
// Created by emerys on 16/3/2.
// Copyright © 2016年 Emerys. All rights reserved.
// #import "ViewController.h" #warning 0000前面四位为消息长度,后接消息,最后以#结束 @interface ViewController ()<NSStreamDelegate,UITableViewDataSource>
{
// 输入流
NSInputStream *inputStream;
// 输出流
NSOutputStream *outputStream;
}
// 用以存储聊天记录,键值为 client_date/service_date
@property (nonatomic,strong) NSMutableArray *history; @property (nonatomic,copy) NSString *msg; @property (weak, nonatomic) IBOutlet UITextField *inputTextField;
@property (weak, nonatomic) IBOutlet UIButton *sendMsgButton;
@property (weak, nonatomic) IBOutlet UITableView *historyTableView; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self loadHistory]; self.historyTableView.dataSource = self; [self connect];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} /**
* @brief 懒加载字典
*/
-(NSMutableArray *)history{
if (!_history) {
_history = [NSMutableArray array];
}
return _history;
}
/**
* @brief 开启链接
*/
-(void)connect{
// 1.建立连接
NSString *host = @"127.0.0.1";
int port = ; // 定义C语言输入输出流
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readStream, &writeStream); // 把C语言的输入输出流转化成OC对象
inputStream = (__bridge NSInputStream *)(readStream);
outputStream = (__bridge NSOutputStream *)(writeStream);
// 设置代理
inputStream.delegate = self;
outputStream.delegate = self; // 把输入输入流添加到主运行循环
// 不添加主运行循环 代理有可能不工作
[inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; // 打开输入输出流
[inputStream open];
[outputStream open];
}
/**
* @brief 开启输入/出流监听
*/
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{ switch (eventCode) {
case NSStreamEventNone:{ }
break;
case NSStreamEventOpenCompleted:{
// 打开
// [self showAlertMessage:@"连接服务器成功"];
NSLog(@"ok");
}
break;
case NSStreamEventHasBytesAvailable:{
// 有数据可读
[self readData];
}
break; case NSStreamEventHasSpaceAvailable:{
// 可发
if (self.msg) {
[self writeData];
} }
break; case NSStreamEventErrorOccurred:{
// 链接错误,那么重新链接
[self connect];
}
break; case NSStreamEventEndEncountered:{
// 结束链接,关闭流,从主运行循环移开
[inputStream close];
[outputStream close]; [inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
break; default:
break;
} }
/**
* @brief 读取数据
*/
-(void)readData{
// 设置1024字节的缓冲区
uint8_t buf[]; NSInteger length = [inputStream read:buf maxLength:]; if (length > ) {
NSData *data = [NSData dataWithBytes:buf length:length];
#warning 在此编码方式不同可能会引起str为空,添加进数组时程序崩溃
// gb2312
NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingGB_18030_2000); NSString *str = [[NSString alloc] initWithData:data encoding:encoding]; // NSLog(@"%@",str);
[self.history addObject:str];
[self.historyTableView reloadData];
[self saveData];
} }
/**
* @brief 发送数据
*/
-(void)writeData{
NSString *msg = self.msg;
NSString *head;
NSUInteger msgLength = msg.length;
// 超出最大限制,或没有数据, 则不发
if (!msgLength && msgLength >= ) {
[self showAlertMessage:@"您发送的数据长度超出限度,请重新编辑"];
}else{
if (msgLength < ) {
head = [NSString stringWithFormat:@"000%li",msgLength];
}else if(msgLength >= && msgLength < ){
head = [NSString stringWithFormat:@"00%li",msgLength];
}else if (msgLength >= && msgLength < ){
head = [NSString stringWithFormat:@"0%li",msgLength];
}else if (msgLength >= && msgLength < ){
head = [NSString stringWithFormat:@"%li",msgLength];
}
NSString *str = [NSString stringWithFormat:@"%@%@#",head,msg]; NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding]; [outputStream write:data.bytes maxLength:data.length];
self.msg = nil;
[self.history addObject:msg];
[self.historyTableView reloadData];
[self saveData];
} }
/**
* @brief 显示一些提示信息
* @param msg 表示将要显示的信息
*/
-(void)showAlertMessage:(NSString *)msg{
__block UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:msg preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[alert dismissViewControllerAnimated:YES completion:nil];
alert = nil;
}];
[alert addAction:action];
[self presentViewController:alert animated:YES completion:nil];
}
/**
* @brief 发送数据按钮回调
*/
- (IBAction)senMessage:(id)sender {
NSString *msg = self.inputTextField.text;
// NSString *head;
NSUInteger msgLength = msg.length;
// 超出最大限制或没有数据, 则不发
if (!msgLength && msgLength >= ) {
[self showAlertMessage:@"您发送的数据长度超出限度,请重新编辑"];
}else{
self.msg = msg;
[self stream:outputStream handleEvent:NSStreamEventHasSpaceAvailable];
} } #pragma mark 数据源
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return ;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.history count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
}
NSString *str = self.history[indexPath.row];
cell.textLabel.text = str;
return cell;
}
/**
* @brief 检测文件是否存在
*/
-(BOOL)checkFile{
// NSString *dPath = [NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) firstObject];
NSString *home = NSHomeDirectory();
NSString *path = [home stringByAppendingPathComponent:@"documents/history.plist"]; NSFileManager *manager = [NSFileManager defaultManager];
return [manager fileExistsAtPath:path];
} /**
* @brief 保存数据到本地
*/
-(void)saveData{ if (self.history.count) { NSString *home = NSHomeDirectory();
NSString *path = [home stringByAppendingPathComponent:@"documents/history.plist"];
if([self.history writeToFile:path atomically:YES]){
NSLog(@"save ok");
}else{
NSLog(@"save error");
} } }
/**
* @brief 读取历史数据
*/
-(void)loadHistory{
NSString *home = NSHomeDirectory();
NSString *path = [home stringByAppendingPathComponent:@"documents/history.plist"]; NSArray *array = [NSArray arrayWithContentsOfFile:path];
if (array.count) {
[self.history addObjectsFromArray:array];
[self.historyTableView reloadData];
} } @end

iOS socket编程的更多相关文章

  1. iOS Socket编程-C语言版(TCP)

    . TCP Socket编程 TCP是面向连接的,安全可靠的传输层协议.TCP的程序基本框架设计图: TCP的程序基本框架设计图.jpg 注意:Socket通信一定有要服务端和客户端. 1.1 TCP ...

  2. iOS Socket编程-C语言版(UDP)

    . UDP Socket编程 先讲一讲UDP编程,因为比TCP要简单多了.首先,我们需要明白UDP是用户数据报协议,英文名为User Datagram Protocol,它是面向无连接的. 注意:So ...

  3. iOS socket编程 第三方库 AsyncSocket(GCDAsyncSocket)

    Socket描述了一个IP.端口对.它简化了程序员的操作,知道对方的IP以及PORT就可以给对方发送消息,再由服务器端来处理发送的这些消息.所以,Socket一定包含了通信的双发,即客户端(Clien ...

  4. IOS socket编程--Asyncsocket

    iPhone的标准推荐是CFNetwork 库编程,其封装好的开源库是 cocoa AsyncSocket库,用它来简化CFNetwork的调用,它提供了异步操作 主要特性有: 队列的非阻塞的读和写, ...

  5. IOS - socket 编程初体验

    #import "ViewController.h" @interface ViewController () <NSStreamDelegate, UITextFieldD ...

  6. iOS Socket编程(一)基本概念

    1.Socket的解释 Socket翻译过来中文称为套接字, 这里我找到了一段比较官方的解释Socket是什么东西: Socket是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元,包含进行 ...

  7. 《网络安全编程基础》之Socket编程

    <网络安全编程基础>之Socket编程 我的代码 server.c // server.cpp : Defines the entry point for the console appl ...

  8. iOS 网络编程:socket

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  9. iOS网络编程笔记——Socket编程

    一.什么是Socket通信: Socket是网络上的两个程序,通过一个双向的通信连接,实现数据的交换.这个双向连路的一端称为socket.socket通常用来实现客户方和服务方的连接.socket是T ...

随机推荐

  1. Unity 利用Coroutine实现跳动数字效果

    纯粹转载:转载注明参考链接! 参考链接:http://xataxnova.blog.163.com/blog/static/236620063201451061738122/,作者:网易博客 xata ...

  2. KK的新书《必然》对未来科技趋势的预言

    是他第一次在<失控>中提示我们--  要用生物学而不是机械学的角度看待这个世界.  是他第一次在<科技想要什么>提示我们--  科技本身就是一个生命体.  而在新书<必然 ...

  3. 踩过的坑之-----selector

    打算踏踏实实的做技术了,以前总是毛毛躁躁的将代码粘贴复制完事能跑起来就行.最近慢慢感觉这样真的对自己的时间和经历是一种浪费. 就从最基本的做起吧,今天做了一个selector,在按钮上面添加效果, & ...

  4. iOS开发:使用Tab Bar切换视图

    iOS开发:使用Tab Bar切换视图 上一篇文章提到了多视图程序中各个视图之间的切换,用的Tool Bar,说白了还是根据触发事件使用代码改变Root View Controller中的Conten ...

  5. unity3d ppsspp模拟器中的post processing shader在unity中使用

    这个位置可以看到ppsspp的特殊处理文件位置来看看这些特效 用来测试的未加特效图片 ppsspp: 传说系列一生爱---英杰传说 最后的战士 aacolor 是关于饱和度,亮度,对比度,色调的调节, ...

  6. Java---网络蜘蛛-网页邮箱抓取器~源码

    刚刚学完Socket,迫不及待的做了这个网页邮箱抓取~~~ 现在有越来越多的人热衷于做网络爬虫(网络蜘蛛),也有越来越多的地方需要网络爬虫,比如搜索引擎.资讯采集.舆情监测等等,诸如此类.网络爬虫涉及 ...

  7. 数据导出到Excel中

    自己修改后的一个数据导出到Excel的方法,粘出来与大家共享. 只需要将             System.Web.HttpContext.Current.Response.Charset =   ...

  8. LaTeX手动安装宏包(package)以及生成帮助文档的整套流程

    注意:版权所有,转载请注明出处. 我使用的是ctex套装,本来已经自带了许多package,但是有时候还是需要使用一些没有预装的宏包,这时就需要自己安装package了.下载package可以从CTA ...

  9. [Java] Java IO 概况

    Java IO 是 Java 的一套 API, 用于读入和写出数据(输入和输出).Java IO API 位于 java.io package.实际上 java.io package 没有解决所有的输 ...

  10. 天津Uber优步司机奖励政策(1月18日~1月24日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...