主要函数:
第一步:创建
CFSocketRef CFSocketCreate(
CFAllocatorRef allocator, //内存分配类型一般为默认KCFAllocatorDefault
SInt32 protocolFamily, //协议族,一般为Ipv4:PF_INET,(Ipv6,PF_INET6)
SInt32 socketType, //套接字类型TCP:SOCK_STREAM
UDP:SOCK_DGRAM
SInt32 protocol, //套接字协议TCP:IPPROTO_TCP
UDP:IPPROTO_UDP;
CFOptionFlags callBackTypes, //回调事件触发类型
Enum CFSocketCallBACKType{
KCFSocketNoCallBack = 0,
KCFSocketReadCallBack =1,
KCFSocketAcceptCallBack = 2,(常用)
KCFSocketDtatCallBack = 3,
KCFSocketConnectCallBack = 4,
KCFSocketWriteCallBack = 8
}
CFSocketCallBack callout, // 触发时调用的函数
Const CFSocketContext *context // 用户定义数据指针
)
假设_socket = CFSocketCreate(….);
第二步:初始化
int yes = 1 ;
setsocketopt(
CFSocketGetNative(_socket),//返回系统原生套接字,补齐缺省
SOL_SOCKET,
SO_REUSEADDR,
(void*)&yes,
sizeof(yes)
) //对socket进行定义设置
第三步:地址
uint16_t port = 12345;
struct sockaddr_in addr4; // 定义监听地址以及端口
memset(&addr4 , 0, sizeof (addr4));
addr4.sin_len = sizeof (addr4);
addr4.sin_family = AF_INET;
addr4.sin_port =htons(port)
addr4.sin_addr.s_addr = htonl(INADDR_ANY);
CFData Ref address =CFDataCreate(
kCFAllocatorDefault,
(UInt8 *)& addr4,
sizeof (addr4),
)
int rst = CFSocketSetAddress(_socket ,&addr4);
//将设置数据设入socket
If ( rst != KCFSocketSuccess )
{…}
第四步:执行
CFRunLoopRef cfrl = CFRunLoopGetCurrent();
//获取当前的运行循环
CFRunLoopSourceRef sourceRef =
CFSoceketCreateRunLoopSource(KCFAllocatorDefault, _socket,0);
//创建一个运行循环源对象
CFRunLoopSource( cfrl , sourceRef, KCFRunLoopCommonModes);
//以该对象运行到当前运行循环中
CFRelease(sourceRef);
服务端响应
CFSocketCallBack callout, // 触发时调用的函数
该函数会在接收到客户端请求连接时触发:
ServerAcceptCallBack( //名字可以任意取,但参数是固定的
CFSoceketRef socket ,
CFSocketCallBackType callbacktype,
CFDataRef address,
const void * data, //与回调函数有关的特殊数据指针,
对于接受连接请求事件,这个指针指向该socket的句柄,
对于连接事件,则指向Sint32类型的错误代码
void *info) //与套接字关联的自定义的任意数据
{ //实现函数
If(kCFSocketAcceptCallBack = = type ){
CFSocketNativeHandle nativeSocketHandle = (CFSocketNativeHandle*)data;
//以下片段用于输出来访者地址
Uint8_t name[SOCK_MAXADDRLEN]
Socklen_t namelen = sizeof(name);
If(0 != getpeername(nativeSocketHandle ,(struct sockaddr_in*)name,&namelen)) //获取地址
{
exit(1)
}
Printf(“%s connected\n”,inet_ntoa((struct sockaddr_in *)name)->sin_addr);
//
CFReadStreamRef iStream;
CFWriteStreamRef oStream;
CFStreamCreatePairWithSocket( // 创建一个可读写的socket连接
kCFAllocatorDefault,
nativeSocketHandle,
&iStream,
&oStream);
If(iStream && oStream){
CFStreamClinetContext streamCtxt = {0,NULL, NULL, NULL, NULL};
If(!CFReadStreamSetClient(
iStream,
kCFStreamEventHasBytesAvailable //有可用数据则执行
readStream, //设置读取时候的函数
&steamCtxt))
{exit(1);}
If(!CFWriteStreamSetClient( //为流指定一个在运行循环中接受回调的客户端
oStream,
kCFStreamEventCanAcceptBytes, //输出流准备完毕,可输出
writeStream, //设置写入时候的函数
&steamCtxt))
{exit(1);}
}
}
}
读取流操作(触发式,被动技能)
readStream(CFReadStreamRef stream,CFStreamEventType eventType, void *client CallBackInfo)
{
UInt8 buff[255];
CFReadStreamRead(stream,buff,255); //将输入流中数据存入buff
Printf(“received %s”,buff);
}
CFWriteStreamRef outputStream = NULL; //输出流
写入流操作(仍然被动技能,在输出流准备好的时候调用)
writeStream (CFWriteStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo)
{
outputStream = stream; //输出流被指定
}
//主动输出,在输出流准备好之后才能调用
FucForWrite()
{
UInt8 buff[] = “Hunter21,this is Overlord”;
If(outputStream != NULL)
{
CFWriteStreamWrite(outputStream,buff,strlen(buff)+1);
}
}
------------------------------------------------------------------------------------------
ios编程笔记:CFSocket(客户端)
CFSocketRef _socket;
-(void)Connect
{
//创建套接字//
CFSocketContext CTX = {0,NULL,NULL,NULL,NULL};
_socket = CFSocketCreate(
kCFAllocatorDefault,
PF_INET,
SOCK_STREAM,
IPPROTO_TCP,
kCFSocketConnectCallBack, // 类型,表示连接时调用
ServerConnectCallBack, // 调用的函数
)
设置地址///
NSString *serverAddr = @"192.168.0.110";
struct sockaddr_in addr
memset(&addr , 0,sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(12345);
addr.sin_addr.s_addr = inet_addr([serverAddr UTF8String]);
CFDataRef address = CFDataCreate(
kCFAllocatorDefault,
(UInt8*)&addr,
sizeof(addr));
/执行连接/
CFSocketConnectToAddress(_socket,address,-1);
CFRunLoopRef cfrl = CFRunLoopGetCurrent(); // 获取当前运行循环
CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault,_socket,0);//定义循环对象
CFRunLoopAddSource(cfrl,source,kCFRunLoopCommonModes); //将循环对象加入当前循环中
CFRelease(source);
}
static void ServerConnectCallBack(
CFSocketRef socket,
CFSocketCallBackType type,
CFDataRef address,
const void *data,
void * info)
{
if(data != NULL)
{
printf("connect").//服务器那边已经提过,连接事件时该指针用于存放报错
}
else
{
printf("connect success");
}
}
///监听来自服务器的信息///
-(void)ReadStream
{
char buffer[255];
while(recv( CFSocektGetNative(_socket),buffer,sizeof(buffer),0))
{
printf(buffer);
}
}
/发送信息给服务器
- (void) sendMessage
{
NSString *stringToSend = @"Overlord,this is Hunter21";
const char *data = [stringToSend UTF8String];
send(CFSocketGetNative(_socket), data, strlen(data) + 1, 0);
}