一,iOS网络编程层次模型
-
Cocoa层:NSURL,Bonjour,Game Kit,WebKit
-
Core Foundation层:基于 C 的 CFNetwork 和 CFNetServices
-
OS层:基于 C 的 BSD socket
二,BSD socket API 简介
API接口 | 讲解 |
int protocol)
int close(int socketFileDescriptor) | |
int bind(int socketFileDescriptor,
| |
| |
| |
hostent* gethostbyname(char *hostname)
| 使用 DNS 查找特定主机名字对应的 IP 地址。如果找不到对应的 IP 地址则返回 NULL。 |
| |
| |
| |
|
三,服务器工作流程
四,客户端工作流程
-
客户端调用 socket(...) 创建socket;
-
客户端调用 connect(...) 向服务器发起连接请求以建立连接;
-
客户端与服务器建立连接之后,就可以通过 send(...)/receive(...)向服务器端发送或从服务器端接收数据;
-
客户端调用 close 关闭 socket;
五,客户端代码示例
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
|
- (
void
)loadDataFromServerWithURL:(NSURL *)url
{
NSString * host = [url host];
NSNumber * port = [url port];
// Create socket
//
int
socketFileDescriptor = socket(AF_INET, SOCK_STREAM,
0
);
if
(-
1
== socketFileDescriptor) {
NSLog(@
"Failed to create socket."
);
return
;
}
// Get IP address from host
//
struct hostent * remoteHostEnt = gethostbyname([host UTF8String]);
if
(NULL == remoteHostEnt) {
close(socketFileDescriptor);
[self networkFailedWithErrorMessage:@
"Unable to resolve the hostname of the warehouse server."
];
return
;
}
struct in_addr * remoteInAddr = (struct in_addr *)remoteHostEnt->h_addr_list[
0
];
// Set the socket parameters
//
struct sockaddr_in socketParameters;
socketParameters.sin_family = AF_INET;
socketParameters.sin_addr = *remoteInAddr;
socketParameters.sin_port = htons([port intValue]);
// Connect the socket
//
int
ret = connect(socketFileDescriptor, (struct sockaddr *) &socketParameters, sizeof(socketParameters));
if
(-
1
== ret) {
close(socketFileDescriptor);
NSString * errorInfo = [NSString stringWithFormat:@
" >> Failed to connect to %@:%@"
, host, port];
[self networkFailedWithErrorMessage:errorInfo];
return
;
}
NSLog(@
" >> Successfully connected to %@:%@"
, host, port);
NSMutableData * data = [[NSMutableData alloc] init];
BOOL waitingForData = YES;
// Continually receive data until we reach the end of the data
//
int
maxCount =
5
;
// just for test.
int
i =
0
;
while
(waitingForData && i < maxCount) {
const
char * buffer[
1024
];
int
length = sizeof(buffer);
// Read a buffer's amount of data from the socket; the number of bytes read is returned
//
int
result = recv(socketFileDescriptor, &buffer, length,
0
);
if
(result >
0
) {
[data appendBytes:buffer length:result];
}
else
{
// if we didn't get any data, stop the receive loop
//
waitingForData = NO;
}
++i;
}
// Close the socket
//
close(socketFileDescriptor);
[self networkSucceedWithData:data];
}
|
1
2
3
4
|
NSThread * backgroundThread = [[NSThread alloc] initWithTarget:self
selector:@selector(loadDataFromServerWithURL:)
object:url];
[backgroundThread start];
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
- (
void
)networkFailedWithErrorMessage:(NSString *)message
{
// Update UI
//
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@
"%@"
, message);
self.receiveTextView.text = message;
self.connectButton.enabled = YES;
[self.networkActivityView stopAnimating];
}];
}
- (
void
)networkSucceedWithData:(NSData *)data
{
// Update UI
//
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSString * resultsString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@
" >> Received string: '%@'"
, resultsString);
self.receiveTextView.text = resultsString;
self.connectButton.enabled = YES;
[self.networkActivityView stopAnimating];
}];
}
|