//
// 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. API-Framework 前后端分离

  2. yield用法

    yield的__next__()和send()的用法,详见代码 def D(): n = 1 while n < 5: m = yield n print("m:",m) p ...

  3. spark运行时出现Neither spark.yarn.jars nor spark.yarn.archive is set错误的解决办法(图文详解)

    不多说,直接上干货! 福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑          ...

  4. Linux下MySQL数据库主从同步配置

    说明: 操作系统:CentOS 5.x 64位 MySQL数据库版本:mysql-5.5.35 MySQL主服务器:192.168.21.128 MySQL从服务器:192.168.21.129 准备 ...

  5. pat1006. Sign In and Sign Out (25)

    1006. Sign In and Sign Out (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue ...

  6. 生成ks.cfg文件

    RHEL 7下生成ks.cfg文件 环境 + RHEL 7 + 字符界面, 没有安装图形界面 软件包安装 + `yum install system-config-kickstart -y` + `y ...

  7. mysql 索引、查询优化

    查询计划Explain mysql查询过程中,如若想了解当前sql的执行计划,可以通过explain your_sql的方式查看,具体可以参考mysql官方解释:https://dev.mysql.c ...

  8. linux查看占用内存最多的程序

    1.linux查看占用内存最多的程序 ps aux|head -1;ps aux|grep -v PID|sort -rn -k +4|head 2.查看占用cpu最多的程序 ps aux|head ...

  9. [转]EntityFramework中常用的数据修改方式

    本文转自:http://blog.csdn.net/itmaxin/article/details/47662151 上一篇文章里提到了 EntityFramework中常用的数据删除方式,那么修改对 ...

  10. 适用于所有页面的基础样式base.css

    @charset "UTF-8"; /*css 初始化 */ html, body, ul, li, ol, dl, dd, dt, p, h1, h2, h3, h4, h5, ...