//
// 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. PIE SDK算法的同步调用

    1.    算法功能简介 同步调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为. PIE SDK支持算法功能的执行,下面对算法的同步调用功能进行介绍. 2.    算法功能实现说明 2. ...

  2. centos7.3下安装redis3.2 yum安装

    1.进入centos 2.运行:yum install redis 3.安装完成后,选择y,确认 4.进入:cd /etc/;vi redis.conf 将,daemonize 修改为yes,并且添加 ...

  3. 「bzoj1003」「ZJOI2006」物流运输 最短路+区间dp

    「bzoj1003」「ZJOI2006」物流运输---------------------------------------------------------------------------- ...

  4. java url生成二维码保存到本地

    http://blog.sina.com.cn/s/blog_5a6efa330102v1lb.html http://blog.csdn.net/about58238/article/details ...

  5. rsync的配置

    1. 安装rsync,如果要讲1.1.1.1的数据备份到2.2.2.2上,则在1.1.1.1上配置如下: /etc/rsyncd.conf uid = nobody gid = nobody use ...

  6. 51nod 1245 Binomial Coefficients Revenge

    Description C(M,N) = M! / N! / (M - N)! (组合数).给出M和质数p,求C(M,0), C(M,1)......C(M,M)这M + 1个数中,有多少数不是p的倍 ...

  7. Jascript面向对象

    JavaScript 的核心是支持面向对象的,同时它也提供了强大灵活的 OOP 语言能力.本文从对面向对象编程的介绍开始,带您探索 JavaScript 的对象模型,最后描述 JavaScript 当 ...

  8. 分页存储过程ROW_NUMBER() over(order by pid desc)

    分页存储过程 : create proc usp_GetMyPhotos  @pageIndex int,   --当前页码  @pageSize int,   --每页多少条  @pageCount ...

  9. 获取当前的日期时间的js函数,格式为“yyyy-MM-dd hh:mm:ss”

    //获取当前的日期时间函数,格式为“yyyy-MM-dd hh:mm:ss” function getNowFormatDate(date) { if (date == null) { var dat ...

  10. python中操作列表

    1.遍历列表 可以用for循环遍历打印非常实用 摸板: for 临时变量 in 列表 : print(临时变量) 注意缩进 , 注意冒号 2.创建数值列表 (1)使用range()函数 , 函数的范围 ...