//
// ViewController.m
// 05.聊天室
//
// Created by apple on 14/12/5.
// Copyright (c) heima. All rights reserved.
// #import "ViewController.h" @interface ViewController ()<NSStreamDelegate,UITextFieldDelegate,UITableViewDataSource,UITableViewDelegate>{
NSInputStream *_inputStream;//对应输入流
NSOutputStream *_outputStream;//对应输出流
}
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *inputViewConstraint;
@property (weak, nonatomic) IBOutlet UITableView *tableView; @property (nonatomic, strong) NSMutableArray *chatMsgs;//聊天消息数组 @end @implementation ViewController -(NSMutableArray *)chatMsgs{
if (!_chatMsgs) {
_chatMsgs = [NSMutableArray array];
} return _chatMsgs;
} - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. // 2.收发数据
// 做一个聊天
// 1.用户登录
// 2.收发数据 // 监听键盘
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kbFrmWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
} -(void)kbFrmWillChange:(NSNotification *)noti{
NSLog(@"%@",noti.userInfo); // 获取窗口的高度 CGFloat windowH = [UIScreen mainScreen].bounds.size.height; // 键盘结束的Frm
CGRect kbEndFrm = [noti.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
// 获取键盘结束的y值
CGFloat kbEndY = kbEndFrm.origin.y; self.inputViewConstraint.constant = windowH - kbEndY;
} -(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
NSLog(@"%@",[NSThread currentThread]); // NSStreamEventOpenCompleted = 1UL << 0,//输入输出流打开完成
// NSStreamEventHasBytesAvailable = 1UL << 1,//有字节可读
// NSStreamEventHasSpaceAvailable = 1UL << 2,//可以发放字节
// NSStreamEventErrorOccurred = 1UL << 3,// 连接出现错误
// NSStreamEventEndEncountered = 1UL << 4// 连接结束
switch (eventCode) {
case NSStreamEventOpenCompleted:
NSLog(@"输入输出流打开完成");
break;
case NSStreamEventHasBytesAvailable:
NSLog(@"有字节可读");
[self readData];
break;
case NSStreamEventHasSpaceAvailable:
NSLog(@"可以发送字节");
break;
case NSStreamEventErrorOccurred:
NSLog(@" 连接出现错误");
break;
case NSStreamEventEndEncountered:
NSLog(@"连接结束"); // 关闭输入输出流
[_inputStream close];
[_outputStream close]; // 从主运行循环移除
[_inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[_outputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
break;
default:
break;
} } - (IBAction)connectToHost:(id)sender {
// 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];
} - (IBAction)loginBtnClick:(id)sender { // 登录
// 发送用户名和密码
// 在这里做的时候,只发用户名,密码就不用发送 // 如果要登录,发送的数据格式为 "iam:zhangsan";
// 如果要发送聊天消息,数据格式为 "msg:did you have dinner"; //登录的指令
NSString *loginStr = @"iam:zhangsan"; //把Str转成NSData
NSData *data = [loginStr dataUsingEncoding:NSUTF8StringEncoding]; [_outputStream write:data.bytes maxLength:data.length];
} #pragma mark 读了服务器返回的数据
-(void)readData{ //建立一个缓冲区 可以放1024个字节
uint8_t buf[]; // 返回实际装的字节数
NSInteger len = [_inputStream read:buf maxLength:sizeof(buf)]; // 把字节数组转化成字符串
NSData *data = [NSData dataWithBytes:buf length:len]; // 从服务器接收到的数据
NSString *recStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@",recStr); [self reloadDataWithText:recStr]; } -(BOOL)textFieldShouldReturn:(UITextField *)textField{ NSString *text = textField.text; NSLog(@"%@",text);
// 聊天信息
NSString *msgStr = [NSString stringWithFormat:@"msg:%@",text]; //把Str转成NSData
NSData *data = [msgStr dataUsingEncoding:NSUTF8StringEncoding]; // 刷新表格
[self reloadDataWithText:msgStr]; // 发送数据
[_outputStream write:data.bytes maxLength:data.length]; // 发送完数据,清空textField
textField.text = nil; return YES;
} -(void)reloadDataWithText:(NSString *)text{
[self.chatMsgs addObject:text]; [self.tableView reloadData]; // 数据多,应该往上滚动
NSIndexPath *lastPath = [NSIndexPath indexPathForRow:self.chatMsgs.count - inSection:];
[self.tableView scrollToRowAtIndexPath:lastPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
} #pragma mark 表格的数据源 -(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]; cell.textLabel.text = self.chatMsgs[indexPath.row]; return cell;
} -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
[self.view endEditing:YES];
}
@end

IOS 连接服务器(socket)的更多相关文章

  1. python socket连接服务器获取回显

    军训回来了,皮皮..... import socket import sys try: s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #创建一个 ...

  2. 阿里云ECS服务器socket无法连接的问题

    把自己的项目部署到阿里云ecs服务器之后,只有127.0.0.1才能连接到服务器端,检查了阿里云安全组规则,以及socket绑定的地址无误后,发现没有开启服务器防火墙的对应端口. firewall-c ...

  3. iOS开发之Socket通信实战--Request请求数据包编码模块

    实际上在iOS很多应用开发中,大部分用的网络通信都是http/https协议,除非有特殊的需求会用到Socket网络协议进行网络数 据传输,这时候在iOS客户端就需要很好的第三方CocoaAsyncS ...

  4. ios专题 - socket(1)

    二,BSD socket API 简介 BSD socket API 和 winsock API 接口大体差不多,下面将列出比较常用的 API: API接口 讲解 int socket(int add ...

  5. iOS学习之Socket使用简明教程- AsyncSocket

    转载自:http://my.oschina.net/joanfen/blog/287238 如果需要在项目中像QQ微信一样做到即时通讯,必须使用socket通讯,本人也是刚学习,分享一下,有什么不对的 ...

  6. 【原】iOS学习之Socket

    Socket在百度百科的定义 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. 相关的描述 Socket的英文原义是“孔”或“插座”.作为BSD UNIX的进 ...

  7. iOS中 HTTP/Socket/TCP/IP通信协议详解

    // OSI(开放式系统互联), 由ISO(国际化标准组织)制定 // 1. 应用层 // 2. 表示层 // 3. 会话层 // 4. 传输层 // 5. 网络层 // 6. 数据链接层 // 7. ...

  8. Linux下巧用my.cnf,mysql连接服务器不需要输入账号密码信息

    Linux下每次用mysql连接连接服务器,常常用如下方式: [root@localhost ~]# mysql -hlocalhost -uroot -p11111 每次都输入用户名,密码,多折腾人 ...

  9. 【iOS干货】☞ Socket

    一.概念 Socket 字面意思又称“套接字” 网络上的两个程序(如,客户端和服务器端)通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. 应用程序一般是先通过Socket来建 ...

随机推荐

  1. Hash算法总结

    1. Hash是什么,它的作用 先举个例子.我们每个活在世上的人,为了能够参与各种社会活动,都需要一个用于识别自己的标志.也许你觉得名字或是身份证就足以代表你这个人,但是这种代表性非常脆弱,因为重名的 ...

  2. 0325img和超链接的学习

    上午学习了cellspacing\cellpadding,img标签以及三种属性,src,alt,title.下午学习了超链接<a></a>,绝对路径与相对路径,锚点链接的使用 ...

  3. How to Create a Cron Job (Scheduled Task) for Your Website or Blog

    How to Create a Cron Job (Scheduled Task) for Your Website or Blog by Christopher Heng, thesitewizar ...

  4. [實現DDD] 第10章 聚合(1)設計原則

    聚合只是將一些實體(Entity)與值對象(Value Object)聚集起來的對象樹嗎?? 有些途徑可能使我們設計出不正確的聚合模型, 如:可能為了對象組合上的方便而將聚合設計的很大;也可能設計的聚 ...

  5. 如何看linux是32位还是64位--转

    地址:http://hi.baidu.com/hehongrong/item/20c296bcf8d834432aebe3b2 如何看linux是32位还是64位 如何看linux是32位还是64位 ...

  6. node使用https,webSocket开启wss

    1. 前言 看WEBRTC教程时使用到WebSocket来传输信令,node端使用了ws库来实现,但在浏览器端http无法获取本地媒体,必须使用https,使用https后webSocket 不能使用 ...

  7. UML建模—EA创建Class(类图)

    1.新建类图 2.添加类或接口 在类图可以捕获系统-类-和模型组件的逻辑结构.它是一个静态模型,描述存在什么,有哪些属性和行为,而不管如何去做. 说明关系之间的类和接口; 泛化. 聚合和关联是在分别反 ...

  8. avalon实现分页组件

    前言 分页组件比较常见,但是用avalon实现的见的不多,这个分页组件,可以适配2种分页方式, 第一种是每次点击下一页,就请求一次后台,并返回当页数据和总条数,我称之为假分页: 第二种是一次性把所有数 ...

  9. AndroidManifest.xml配置文件详解(转载)

     AndroidManifest.xml配置文件详解 2013-01-05 10:25:23 分类: Android平台 AndroidManifest.xml配置文件对于Android应用开发来说是 ...

  10. WPF的依赖项属性

    WPF的依赖项属性 属性与事件是.NET抽象模型的核心部分.WPF使用了更高级的依赖项属性(Dependency Property)功能来替换原来.NET的属性,实现了更高效率的保存机制,还添加了附加 ...