问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

ios cfocketref怎么断开socket

发布网友 发布时间:2022-09-18 03:26

我来回答

1个回答

热心网友 时间:2023-10-20 00:33

IOS上的socket通信
客户端:
导入头文件:
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#import <unistd.h>
1. 创建连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14

CFSocketContext sockContext = {0, // 结构体的版本,必须为0
self,

// 一个任意指针的数据,可以用在创建时CFSocket对象相关联。这个指针被传递给所有的上下文中定义的回调。
NULL, // 一个定义在上面指针中的retain的回调, 可以为NULL
NULL, NULL};
CFSocketRef _socket = (kCFAllocatorDefault, // 为新对象分配内存,可以为nil
PF_INET, // 协议族,如果为0或者负数,则默认为PF_INET
SOCK_STREAM, // 套接字类型,如果协议族为PF_INET,则它会默认为SOCK_STREAM
IPPROTO_TCP, // 套接字协议,如果协议族是PF_INET且协议是0或者负数,它会默认为IPPROTO_TCP
kCFSocketConnectCallBack, // 触发回调函数的socket消息类型,具体见Callback Types
TCPServerConnectCallBack, // 上面情况下触发的回调函数
&sockContext // 一个持有CFSocket结构信息的对象,可以为nil
);

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

if (_socket != nil) {
struct sockaddr_in addr4; // IPV4
memset(&addr4, 0, sizeof(addr4));
addr4.sin_len = sizeof(addr4);
addr4.sin_family = AF_INET;
addr4.sin_port = htons(8888);
addr4.sin_addr.s_addr = inet_addr([strAddress UTF8String]); // 把字符串的地址转换为机器可识别的网络地址

// 把sockaddr_in结构体中的地址转换为Data
CFDataRef address = CFDataCreate(kCFAllocatorDefault, (UInt8 *)&addr4, sizeof(addr4));
CFSocketConnectToAddress(_socket, // 连接的socket
address, // CFDataRef类型的包含上面socket的远程地址的对象
-1 // 连接超时时间,如果为负,则不尝试连接,而是把连接放在后台进行,如果_socket消息类型为kCFSocketConnectCallBack,将会在连接成功或失败的时候在后台触发回调函数
);
CFRunLoopRef cRunRef = CFRunLoopGetCurrent(); // 获取当前线程的循环
// 创建一个循环,但并没有真正加如到循环中,需要调用CFRunLoopAddSource
CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _socket, 0);
CFRunLoopAddSource(cRunRef, // 运行循环
sourceRef, // 增加的运行循环源, 它会被retain一次
kCFRunLoopCommonModes // 增加的运行循环源的模式
);
CFRelease(courceRef);
}

  
2. 设置回调函数
1 // socket回调函数的格式:
2 static void TCPServerConnectCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
3 if (data != NULL) {
4 // 当socket为kCFSocketConnectCallBack时,失败时回调失败会返回一个错误代码指针,其他情况返回NULL
5 NSLog(@"连接失败");
6 return;
7 }
8 TCPClient *client = (TCPClient *)info;
9 // 读取接收的数据
10 [info performSlectorInBackground:@selector(readStream) withObject:nil];
11 }
12 3. 接收发送数据
13 // 读取接收的数据
14 - (void)readStream {
15 char buffer[1024];
16 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
17 while (recv(CFSocketGetNative(_socket), //与本机关联的Socket 如果已经失效返回-1:INVALID_SOCKET
18 buffer, sizeof(buffer), 0)) {
19 NSLog(@"%@", [NSString stringWithUTF8String:buffer]);
20 }
21 }
22 // 发送数据
23 - (void)sendMessage {
24 NSString *stringTosend = @"你好";
25 char *data = [stringTosend UTF8String];
26 send(SFSocketGetNative(_socket), data, strlen(data) + 1, 0);
27 }
28 服务器端:
29 CFSockteRef _socket;
30 CFWriteStreamRef outputStream = NULL;
31 int setupSocket() {
32 _socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, TCPServerAcceptCallBack, NULL);
33 if (NULL == _socket) {
34 NSLog(@"Cannot create socket!");
35 return 0;
36 }
37
38 int optval = 1;
39 setsockopt(CFSocketGetNative(_socket), SOL_SOCKET, SO_REUSEADDR, // 允许重用本地地址和端口
40 (void *)&optval, sizeof(optval));
41
42 struct sockaddr_in addr4;
43 memset(&addr4, 0, sizeof(addr4));
44 addr4.sin_len = sizeof(addr4);
45 addr4.sin_family = AF_INET;
46 addr4.sin_port = htons(port);
47 addr4.sin_addr.s_addr = htonl(INADDR_ANY);
48 CFDataRef address = CFDataCreate(kCFAllocatorDefault, (UInt8 *)&addr4, sizeof(addr4));
49
50 if (kCFSocketSuccess != CFSocketSetAddress(_socket, address)) {
51 NSLog(@"Bind to address failed!");
52 if (_socket)
53 CFRelease(_socket);
54 _socket = NULL;
55 return 0;
56 }
57
58 CFRunLoopRef cfRunLoop = CFRunLoopGetCurrent();
59 CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _socket, 0);
60 CFRunLoopAddSource(cfRunLoop, source, kCFRunLoopCommonModes);
61 CFRelease(source);
62
63 return 1;
64 }
65 // socket回调函数,同客户端
66 void TCPServerAcceptCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
67 if (kCFSocketAcceptCallBack == type) {
68 // 本地套接字句柄
69 CFSocketNativeHandle nativeSocketHandle = *(CFSocketNativeHandle *)data;
70 uint8_t name[SOCK_MAXADDRLEN];
71 socklen_t nameLen = sizeof(name);
72 if (0 != getpeername(nativeSocketHandle, (struct sockaddr *)name, &nameLen)) {
73 NSLog(@"error");
74 exit(1);
75 }
76 NSLog(@"%@ connected.", inet_ntoa( ((struct sockaddr_in *)name)->sin_addr )):
77 CFReadStreamRef iStream;
78 CFWriteStreamRef oStream;
79 // 创建一个可读写的socket连接
80 CFStreamCreatePairWithSocket(kCFAllocatorDefault, nativeSocketHandle, &iStream, &oStream);
81 if (iStream && oStream) {
82 CFStreamClientContext streamContext = {0, NULL, NULL, NULL};
83 if (!CFReadStreamSetClient(iStream, kCFStreamEventHasBytesAvaiable,
84 readStream, // 回调函数,当有可读的数据时调用
85 &streamContext)){
86 exit(1);
87 }
88 if (!CFReadStreamSetClient(iStream, kCFStreamEventCanAcceptBytes, writeStream, &streamContext)){
89 exit(1);
90 }
91 CFReadStreamScheleWithRunLoop(iStream, CFRunLoopGetCurrent(), kCFRunLoopCommomModes);
92 CFWriteStreamScheleWithRunLoop(wStream, CFRunLoopGetCurrent(), kCFRunLoopCommomModes);
93 CFReadStreamOpen(iStream);
94 CFWriteStreamOpen(wStream);
95 } else {
96 close(nativeSocketHandle);
97 }
98 }
99 }
100 // 读取数据
101 void readStream(CFReadStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo) {
102 UInt8 buff[255];
103 CFReadStreamRead(stream, buff, 255);
104 printf("received: %s", buff);
105 }
106 void writeStream (CFWriteStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo) {
107 outputStream = stream;
108 }
109 main {
110 char *str = "nihao";
111
112 if (outputStream != NULL) {
113 CFWriteStreamWrite(outputStream, str, strlen(line) + 1);
114 } else {
115 NSLog(@"Cannot send data!");
116 }
117 }
118 // 开辟一个线程线程函数中
119 void runLoopInThread() {
120 int res = setupSocket();
121 if (!res) {
122 exit(1);
123 }
124 CFRunLoopRun(); // 运行当前线程的CFRunLoop对象
125 }
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
创新5.10060声卡怎么关闭,为什么音质变得很差?我用的是KX 我已经装了声卡,和Kx管理器。可声音听见还是那么幼稚。怎么把声音调的... ...装不上KX3550,声卡是 创新5.1的 装完KX3550重启以后,提示 初始化... 我买了一个创新5.1 0060声卡,玩龙之谷游戏就声音不完全,只有背景音乐... 声卡5.10060KX驱动3550调试怎么弄 win11玩csgo游戏一直闪退什么原因 win11玩csgo游戏一直闪退的解决... 习惯养成心得体会 饥荒ios高脚鸟蛋怎么孵化高脚鸟怎么养 故事的力量可以从什么角度来分析? 地震前为什么要出现地震云 雨人的获奖记录 上海的外滩3号酒吧是如何? 上海外滩三号饮食文化有限公司 华为双卡手机怎么用两个? 梦见自己一个人在店里店里有灯但不怎么亮店一个男人说停电但没看见人但整条街没人没电好黑有阴森感求解梦 梦见别人家没电唯独我家有电 跪求好心人分享未了阴阳情1990年上映的由茱丽叶特·斯蒂文森主演的免费高清百度云资源 谁有《未了阴阳情(1990)》百度云高清资源在线观看,安东尼·明格拉导演的 王嘉尔遇粉丝五角星姿势合影,不知所措“举手投降”,你喜欢他的性格吗? 以后说话先举手是什么梗 怎样让学生自觉参与体育锻炼 如何让孩子坚持长期运动 黄河颂的歌词是什么? 黄河颂歌词内容是什么? 自己的能改吗怎么改? 怎么修改? 可以修改吗? 可以怎么改? 可以更改吗,怎么更改? 微信里的怎么改,不是名字 切蛋糕片一定要用分割器吗 玫瑰花茶会不会褪色 09电大旅行社经营与管理 请问一下商业贷款首房贷款利率是多少 回家的诱惑林品如结局和谁在一起了? 请问回家的诱惑结局品如和谁在一起了? 回家的诱惑结局林品如最后和谁在一起了? 一个手机两个怎么弄 一个手机如何同时登录两个? 一部手机两个怎么弄 一部手机能不能同时用两个 一个手机可以同时登录2个吗?- 问一问 公积金少能贷款买房吗 一个手机登录两个怎么弄 公积金只有几千块可以贷款吗?公积金基数低会被拒绝吗 一个手机号能有两个吗 怎么在一台手机上同时绑定两个 形容乡村山水的诗句? 形容“乡村山水”的诗句有哪些? 四川省乐山中心车站到山东青岛市中心车站需要多少车费?