1.打开安装MySQL的目录,在windows系统中如果是默认路径,应该和我的是一样的:C:\Program Files\MySQL\MySQL Server 8.0
一、建立socket链接,Mac端终端使用nc命令做端口监听,oc作为客户端建立socket连接。使用的工具及使用方法:
nc/netcat(选项)(参数)
-g<网关>:设置路由器跃程通信网关,最多设置8个;
-G<指向器数目>:设置来源路由指向器,其数值为4的倍数;
-h:在线帮助;
-i<延迟秒数>:设置时间间隔,以便传送信息及扫描通信端口;
-l:使用监听模式,监控传入的资料;
-n:直接使用ip地址,而不通过域名服务器;
-o<输出文件>:指定文件名称,把往来传输的数据以16进制字码倾倒成该文件保存;
-p<通信端口>:设置本地主机使用的通信端口;
-r:指定源端口和目的端口都进行随机的选择;
-s<来源位址>:设置本地主机送出数据包的IP地址;
-u:使用UDP传输协议;
-v:显示指令执行过程;
-w<超时秒数>:设置等待连线的时间;
-z:使用0输入/输出模式,只在扫描通信端口时使用。
1、服务端 端口监听
nc -l 6666
2、永久监听TCP端口
nc -lk port
3、临时监听UDP
nc -lu port
4、永久监听UDP
nc -luk port
5、连接服务端
nc -v 127.0.0.1 666
6、端口扫描
nc -v -w 1 127.0.0.1 -z 1-1000
客户端代码:
#import "ViewController.h"
#import <sys/socket.h>
#import <arpa/inet.h>//inet_addr
#define connect_host @"127.0.0.1"
#define connect_port 6666
@interface ViewController (){
int clientSocket
dispatch_queue_t queSerial
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad]
//button
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]
button.frame = CGRectMake((self.view.frame.size.width-200)/2, 100, 200, 30)
button.backgroundColor = [UIColor grayColor]
[button setTitle:@"发送普通文本" forState:UIControlStateNormal]
[button addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside]
[self.view addSubview:button]
button = [UIButton buttonWithType:UIButtonTypeCustom]
button.frame = CGRectMake((self.view.frame.size.width-200)/2, 150, 200, 30)
button.backgroundColor = [UIColor grayColor]
[button setTitle:@"发送图片" forState:UIControlStateNormal]
[button addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside]
[self.view addSubview:button]
button = [UIButton buttonWithType:UIButtonTypeCustom]
button.frame = CGRectMake((self.view.frame.size.width-200)/2, 200, 200, 30)
button.backgroundColor = [UIColor grayColor]
[button setTitle:@"发送文本加图片" forState:UIControlStateNormal]
[button addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside]
[self.view addSubview:button]
[self initSocket]
}
-(void)btn:(UIButton *)button{
if ([button.titleLabel.text isEqualToString:@"发送普通文本"]) {
[self sendMessage:@"发送普通文本"]
}else if ([button.titleLabel.text isEqualToString:@"发送图片"]) {
UIImage *image = [UIImage imageNamed:@"hibo"]
NSData *data = UIImagePNGRepresentation(image)
NSLog(@"height:%f",image.size.height)
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]
NSLog(@"%@",dataString)
//[self sendMessage:dataString]
}else if ([button.titleLabel.text isEqualToString:@"发送文本加图片"]) {
}
}
//发起socket连接
-(BOOL)initSocket{
/*
第一个参数:adress_family,协议簇 AF_INET:IPV4
第二个参数:数据格式->SOCK_STREAM(TCP)/SOCK_DGRAM(UDP)
第三个参数:protocal IPPROTO_TCP,如果为0会根据第二个参数选择合适的协议
返回值:>0成功 -1失败
*/
clientSocket = socket(AF_INET, SOCK_STREAM, 0)
NSLog(@"clientsocket:%d",clientSocket)
if (clientSocket>0) {
NSLog(@"socket create success")
}else{
NSLog(@"socket create error")
}
/*
连接
第一个参数:客户端socket
第二个参数:指向数据结构,socketAddr的指针,其中包括目的端口和IP地址
第三个参数:结构体数据长度
返回值:0成功 其他错误
*/
struct sockaddr_in addr4 = {0}
addr4.sin_family = AF_INET//ipv4
addr4.sin_len = sizeof(addr4)
addr4.sin_addr.s_addr = inet_addr(connect_host.UTF8String)
addr4.sin_port = htons(connect_port)//是将整型变量从主机字节顺序转变成网络字节顺序, 就是整数在地址空间存储方式变为高位字节存放在内存的低地址处
int flag = connect(clientSocket, (const struct sockaddr *)&addr4, sizeof(addr4))
if (!flag) {
[self receiveMessage]
}else{
clientSocket = 0
NSLog(@"连接失败")
}
return flag
}
//接收消息
-(void)receiveMessage{
if (!queSerial) {
queSerial=dispatch_queue_create("jrQueueSerial", DISPATCH_QUEUE_SERIAL)
}
dispatch_async(queSerial, ^{
uint8_t buffer[1024]
ssize_t recvLen = recv(self->clientSocket, buffer, sizeof(buffer), 0)
NSData *data = [NSData dataWithBytes:buffer length:recvLen]
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]
if (recvLen>0) {
NSLog(@"%@:%@",str,[NSThread currentThread])
NSLog(@"%@",str)
[self receiveMessage]
}else{
NSLog(@"连接断开")
self->clientSocket = 0
}
})
}
//发送消息
-(BOOL)sendMessage:(NSString *)message{
if (clientSocket==0) {
BOOL flag = [self initSocket]
if (!flag)return NO
}
ssize_t sendLen = send(clientSocket, message.UTF8String, strlen(message.UTF8String), 0)
NSLog(@"发送消息长度:%zd",sendLen)
return sendLen>=0
}
@end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
1、在终端执行命令监听端口6666:
nc -l 127.0.0.1 6666
1
1
进入等待连接状态。
2、执行以上oc代码进行socket连接:
client_socket.png
3、以上连接成功,由服务端发送一条消息,客户端接收打印如下:
client_receive.png
注:以上代码中图片发送及文本+图片发送未完成。
二、oc模拟服务端代替Mac终端命令,一步步实现服务端的三次握手及通信。主要使用方法:
1、创建一个socket:
socket(AF_INET, SOCK_STREAM, 0)
1
1
第一个参数:address_family,协议簇 AF_INET对应的IPV4;
第二个参数:数据格式可选两种SOCK_STREAM(TCP)、SOCK_DGRAM(UDP);
第三个参数:protocal IPPROTO_TCP,设置为0会根据第二个参数选择相应的协议;
返回值:sockaddr -1失败 其他成功为socket标号1、2、3、 4,指示为当前socket。
2、端口绑定:
bind(sockaddr, (const struct sockaddr *)&addr4, sizeof(addr4))
1
1
第一个参数:创建的socket描述号;
第二个参数:对应socketaddr_in(对应IPV4)的结构体包含了端口号;
第三个参数:socketaddr_in结构体长度。
3、监听端口:
listen(sockaddr, 5)
1
1
第一个参数:创建的socket标号;
第二个参数:可以排队的最大连接个数。
4、获取连接的socket标号和以上使用的标号不同
accept(sockaddr, (struct sockaddr *)&aptsockaddr, &addrLen)
1
1
第一个参数:创建的socket描述号;
第二个参数:可以排队的最大连接个数;
返回值:接收后的socket标号。
5、接收客户端消息:
recv(aptsocket, buffer, len, 0)
1
1
第一个参数:accept返回的标号理解为当前socket;
第二个参数:接收字符的缓存变量;
第三个参数:一般设置0;
返回值:接收到的数据长度。
6、发送消息:
send(aptsocket, message.UTF8String, strlen(message.UTF8String), 0)
1
1
第一个参数:accept返回的标号理解为当前socket;
第二个参数:发送的消息字符char *型数据;
第三个参数:一般设置0;
返回值:发送的数据长度。
服务端代码:
/*
ipv6
struct sockaddr_in6 addr6 = {0}
bzero(&addr6, sizeof(addr6))
addr6.sin6_len = sizeof(addr6)
addr6.sin6_family = AF_INET6
addr6.sin6_port = htons(connect_port)
htons将主机的无符号短整形数转换成网络字节顺序
htonl将主机的无符号长整形数转换成网络字节顺序
*/
#import "ViewController.h"
#import <sys/socket.h>
#import <arpa/inet.h>//inet_addr
#define connect_host @"127.0.0.1"
#define connect_port 6666
@interface ViewController ()
{
int sockaddr//创建的socket地址
int aptsocket//同意后返回的socket地址
dispatch_queue_t queSerial//接收消息的队列
BOOL socket_flag//socket标识
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad]
//button
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]
button.frame = CGRectMake((self.view.frame.size.width-200)/2, 100, 200, 30)
button.backgroundColor = [UIColor grayColor]
[button setTitle:@"回复文本" forState:UIControlStateNormal]
[button addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside]
[self.view addSubview:button]
button = [UIButton buttonWithType:UIButtonTypeCustom]
button.frame = CGRectMake((self.view.frame.size.width-200)/2, 150, 200, 30)
button.backgroundColor = [UIColor grayColor]
[button setTitle:@"关闭链接" forState:UIControlStateNormal]
[button addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside]
[self.view addSubview:button]
button = [UIButton buttonWithType:UIButtonTypeCustom]
button.frame = CGRectMake((self.view.frame.size.width-200)/2, 200, 200, 30)
button.backgroundColor = [UIColor grayColor]
[button setTitle:@"创建链接" forState:UIControlStateNormal]
[button addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside]
[self.view addSubview:button]
//创建服务端socket
[self initServerSocket]
}
-(void)btn:(UIButton *)button{
if ([button.titleLabel.text isEqualToString:@"回复文本"]) {
[self sendMessage:@"回复:你好啊!!"]
}else if ([button.titleLabel.text isEqualToString:@"关闭链接"]) {
[self closeSocket]
}else if ([button.titleLabel.text isEqualToString:@"创建链接"]) {
[self initServerSocket]
}
}
//初始化socket
-(BOOL)initServerSocket{
socket_flag = YES
//1、创建一个socket
sockaddr = socket(AF_INET, SOCK_STREAM, 0)
NSLog(@"sockaddr:%d",sockaddr)
if (sockaddr==-1) {
NSLog(@"创建失败")
return NO
}
//ipv4
struct sockaddr_in addr4 = {0}
//参数说明:s 要置零的数据的起始地址; n 要置零的数据字节个数。
memset(&addr4, 0, sizeof(addr4))
addr4.sin_len = sizeof(addr4)
addr4.sin_family = AF_INET
addr4.sin_port = htons(connect_port)//将主机的无符号短整形数转换成网络字节顺序
addr4.sin_addr.s_addr = INADDR_ANY//就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”
//2、端口绑定
int error = bind(sockaddr, (const struct sockaddr *)&addr4, sizeof(addr4))
if (error!=0) {
NSLog(@"绑定失败")
return NO
}
//3、监听端口
error = listen(sockaddr, 5)//开始监听第二个参数可以排队的最大连接个数
if (error!=0) {
NSLog(@"监听失败")
return NO
}
//4、轮询
if (!queSerial) {
queSerial = dispatch_queue_create("receive_queue", DISPATCH_QUEUE_SERIAL)
}
dispatch_async(queSerial, ^{
[self receiveMessage]
})
return YES
}
//轮询接收消息
-(void)receiveMessage{
while (true) {
NSLog(@"currentThread:%@",[NSThread currentThread])
struct sockaddr_in aptsockaddr
socklen_t addrLen = sizeof(aptsockaddr)
//4、获取连接的socket
aptsocket = accept(sockaddr, (struct sockaddr *)&aptsockaddr, &addrLen)
NSLog(@"aptsocket:%d",aptsocket)
if (aptsocket != -1) {
NSLog(@"accept success address:%ss, port:%d",inet_ntoa(aptsockaddr.sin_addr),ntohs(aptsockaddr.sin_port))
char buffer[1024]
ssize_t recvLen
size_t len = sizeof(buffer)
do{
//5、接收客户端的消息
recvLen = recv(aptsocket, buffer, len, 0)
NSString *str = [NSString stringWithCString:buffer encoding:NSUTF8StringEncoding]
NSLog(@"receive:%@",str)
NSLog(@"buffer:%s",buffer)
[self sendMessage:@"回复你:哈哈"]
}while(socket_flag)
}
close(aptsocket)
break//链接失败后跳出轮询
}
}
//发送消息
-(BOOL)sendMessage:(NSString *)message{
if (sockaddr==0) {
NSLog(@"链接已断开")
}
ssize_t sendLen = send(aptsocket, message.UTF8String, strlen(message.UTF8String), 0)
NSLog(@"发送消息长度:%zd",sendLen)
return sendLen>=0
}
//断开链接
-(void)closeSocket{
NSLog(@"关闭链接")
socket_flag = NO
}
@end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
通过以上过程,对socket通信能有一个初步了解,可以利用socket通信搭建一套简单的聊天系统
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)