大家都知道,在iOS中有这些经典的通许协议以及框架,那么他们是怎么来实现我们的聊天的呢?
1)基于Socket原生:代表框架 CocoaAsyncSocket。
2)基于WebScoket:代表框架 SocketRocket。
3)基于MQTT:代表框架 MQTTKit。
4)基于XMPP:代表框架 XMPPFramework
首先需要搞清楚的是,其中MQTT和XMPP为聊天协议,它们是最上层的协议,而WebScoket是传输通讯协议,它是基于Socket封装的一个协议。而通常我们所说的腾讯IM的私有协议,就是基于WebScoket或者Scoket原生进行封装的一个聊天协议。
那么首先我们来模拟一下socket封装协议,实现通讯。
一.node搭建本地服务,socket实现通讯协议
1.首先确认你的mac中是否已经安装了node解释器,然后我们创建一个server.js文件,我们运行这个脚本文件,实现本地服务器的配置启动
这里就是我们配置文件的实现代码
var net = require('net');
var HOST = '127.0.0.1';
var PORT = 3308;
net.createServer(function(sock) {
console.log('CONNECTED: ' +
sock.remoteAddress + ':' + sock.remotePort);
sock.write('服务端发出:连接成功');
sock.on('data', function(data) {
console.log('DATA ' + sock.remoteAddress + ': ' + data);
sock.write('You said "' + data + '"');
});
sock.on('close', function(data) {
console.log('CLOSED: ' +
sock.remoteAddress + ' ' + sock.remotePort);
});
}).listen(PORT, HOST);
console.log('Server listening on ' + HOST +':'+ PORT);
复制代码
我们node server.js启动,发现服务器开始监听
Server listening on 127.0.0.1:3308
2.接着我们在客户端实现socket的聊天协议
TYHSocketManager.h
@interface TYHSocketManager : NSObject
+(instancetype)share;
-(void)connect;
-(void)disConnect;
-(void)sendMsg:(NSString *)msg;
@end
复制代码
TYHSocketManager.m
#import "TYHSocketManager.h"
#import <sys/types.h>
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
@interface TYHSocketManager()
@property (nonatomic, assign) int clientSocket;
@end
@implementation TYHSocketManager
+ (instancetype)share {
static dispatch_once_t onceToken;
static TYHSocketManager *instance = nil;
dispatch_once(&onceToken, ^{
instance = [[self alloc]init];
});
return instance;
}
- (void)initSocket {
`
`if (_clientSocket != 0) {
[self disConnect];
_clientSocket = 0;
}
//创建客户端socket
_clientSocket = CreateClinetSocket();
//服务器IP
//服务器Ip
const char * server_ip="127.0.0.1";
//服务器端口
short server_port= 3308;
//等于0说明连接失败
if (ConnectionToServer(_clientSocket,server_ip, server_port)==0) {
printf("Connect to server error");
return ;
}
//走到这说明连接成功
printf("Connect to server ok");``
}
static int CreateClinetSocket()
{
int ClinetSocket = 0;
//创建一个socket,返回值为Int。(注scoket其实就是Int类型)
//第一个参数addressFamily IPv4(AF_INET) 或 IPv6(AF_INET6)。
//第二个参数 type 表示 socket 的类型,通常是流stream(SOCK_STREAM) 或数据报文datagram(SOCK_DGRAM)
//第三个参数 protocol 参数通常设置为0,以便让系统自动为选择我们合适的协议,对于 stream socket 来说会是 TCP 协议(IPPROTO_TCP),而对于 datagram来说会是 UDP 协议(IPPROTO_UDP)。
ClinetSocket = socket(AF_INET, SOCK_STREAM, 0);
return ClinetSocket;
}
static int ConnectionToServer(int client_socket,const char * server_ip,unsigned short port)
{
//生成一个sockaddr_in类型结构体
struct sockaddr_in sAddr={0};
sAddr.sin_len=sizeof(sAddr);
//设置IPv4
sAddr.sin_family=AF_INET;
//inet_aton是一个改进的方法来将一个字符串IP地址转换为一个32位的网络序列IP地址
//如果这个函数成功,函数的返回值非零,如果输入地址不正确则会返回零。
inet_aton(server_ip, &sAddr.sin_addr);
//htons是将整型变量从主机字节顺序转变成网络字节顺序,赋值端口号
sAddr.sin_port=htons(port);
//用scoket和服务端地址,发起连接。
//客户端向特定网络地址的服务器发送连接请求,连接成功返回0,失败返回 -1。
//注意:该接口调用会阻塞当前线程,直到服务器返回。
if (connect(client_socket, (struct sockaddr *)&sAddr, sizeof(sAddr))==0) {
return client_socket;
}
return 0;
}
#pragma mark -- 新线程接收消息
- (void)pullMsg {
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(recieveAction) object:nil];
[thread start];
}
#pragma mark - 对外逻辑
- (void)connect {
[self initSocket];
}
- (void)disConnect {
close(self.clientSocket);
}
- (void)sendMsg:(NSString *)msg {
const char *send_Message = [msg UTF8String];
send(self.clientSocket, send_Message, strlen(send_Message)+ 1, 0);
}
//收取服务端发送的消息
- (void)recieveAction{
while (1) {
char recv_Message[1024] = {0};
recv(self.clientSocket, recv_Message, sizeof(recv_Message), 0);
printf("%s",recv_Message);
}
}
@end
复制代码
最终的实现结果就是
我们在客户端发起连接,然后在发送消息,在终端是可以接受到消息(注意:如果申请的端口被占用,请kill或者申请其他的)
二.XMPP和openfire实现本地服务通讯
1.首先我们需要在本地下载安装以及搭建数据库,在这我参考的是
www.jianshu.com/p/f06ba0ea7…
它这里面也有下载链接,按照他的操作最后实现偏好设置中是这样的展示,这里有一点特别注意,就是我们首先要在终端中输入sudo su,如果我们直接cd /usr/local/openfire/bin,其实整个过程没什么问题,但是等我们需要打开服务器open Admin Console配置的时候,总是会出现一些小问题而无法进行下去,所以这一步不要丢失。
2.如果前面都实现了,那么我们就能在openfire后台看到一些服务器相关的数据以及用户群信息。
3.刚开始我按照参考链接的处理方式,下载了adium以及spark,配置能够实现通讯
4.但是我们最终的目的是自己写的app进行通讯,所以我在此基础上继续开发,引用XMPP协议框架,实现了app和spark之间的通讯,这也是参考了一些网上的案例,其实到达这的时候就我们就大致清晰了,接下来就是实现聊天的自定义页面了!