常用的Socket类型有两种:流式Socket(SOCK_STREAM) 和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连 接的Socket,对应于无连接的UDP服务应用。
1、socket调用库函数主要有:
创建套接字
1 | Socket(af,type,protocol) |
建立地址和套接字的联系
1 | bind(sockid, local addr, addrlen) |
服务器端侦听客户端的请求
1 | listen( Sockid ,quenlen) |
建立服务器/客户端的连接 (面向连接TCP)
客户端请求连接
1 | Connect(sockid, destaddr, addrlen) |
服务器端等待从编号为Sockid的Socket上接收客户连接请求
1 | newsockid=accept(Sockid,Clientaddr, paddrlen) |
发送/接收数据
面向连接:
1
2
|
send(sockid, buff, bufflen)
recv( )
|
面向无连接:
1
2
|
sendto(sockid,buff,…,addrlen)
recvfrom( )
|
释放套接字
1 | close(sockid) |
tcpsocket的具体实现
服务器的工作流程:首先调用socket函数创建一个Socket,然后调用bind函数将其与本机地址以及一个本地端口号绑定,然后调用 listen在相应的socket上监听,当accpet接收到一个连接服务请求时,将生成一个新的socket。服务器显示该客户机的IP地址,并通过 新的socket向客户端发送字符串" hi,I am server!"。最后关闭该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
|
#import <Foundation/Foundation.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main( int argc, const char * argv[])
{
@autoreleasepool {
// 1
int err;
int fd=socket(AF_INET, SOCK_STREAM , 0);
BOOL success=(fd!=-1);
// 1
// 2
if (success) {
NSLog(@ "socket success" );
struct sockaddr_in addr;
memset (&addr, 0, sizeof (addr));
addr.sin_len= sizeof (addr);
addr.sin_family=AF_INET;
// =======================================================================
addr.sin_port=htons(1024);
// ============================================================================
addr.sin_addr.s_addr=INADDR_ANY;
err=bind(fd, ( const struct sockaddr *)&addr, sizeof (addr));
success=(err==0);
}
// 2
// ============================================================================
if (success) {
NSLog(@ "bind(绑定) success" );
err=listen(fd, 5); //开始监听
success=(err==0);
}
// ============================================================================
//3
if (success) {
NSLog(@ "listen success" );
while ( true ) {
struct sockaddr_in peeraddr;
int peerfd;
socklen_t addrLen;
addrLen= sizeof (peeraddr);
NSLog(@ "prepare accept" );
peerfd=accept(fd, ( struct sockaddr *)&peeraddr, &addrLen);
success=(peerfd!=-1);
// ============================================================================
if (success) {
NSLog(@ "accept success,remote address:%s,port:%d" ,inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port));
char buf[1024];
ssize_t count;
size_t len= sizeof (buf);
do {
count=recv(peerfd, buf, len, 0);
NSString* str = [NSString stringWithCString:buf encoding:NSUTF8StringEncoding];
NSLog(@ "%@" ,str);
} while ( strcmp (buf, "exit" )!=0);
}
// ============================================================================
close(peerfd);
}
}
//3
}
return 0;
}
|
客户端的工作流程:首先调用socket函数创建一个Socket,然后调用bind函数将其与本机地址以及一个本地端口号绑定,请求连接服务器,通过新的socket向客户端发送字符串" hi,I am client!"。最后关闭该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
|
//
// main.m
// kewai_SocketClient
//
#import <Foundation/Foundation.h>
#include <sys/socket.h>
#include <netinet/in.h>
#import <arpa/inet.h>
int main( int argc, const char * argv[])
{
@autoreleasepool {
// 1
int err;
int fd=socket(AF_INET, SOCK_STREAM, 0);
BOOL success=(fd!=-1);
struct sockaddr_in addr;
// 1
// 2
if (success) {
NSLog(@ "socket success" );
memset (&addr, 0, sizeof (addr));
addr.sin_len= sizeof (addr);
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=INADDR_ANY;
err=bind(fd, ( const struct sockaddr *)&addr, sizeof (addr));
success=(err==0);
}
// 2
//3
if (success) {
//============================================================================
struct sockaddr_in peeraddr;
memset (&peeraddr, 0, sizeof (peeraddr));
peeraddr.sin_len= sizeof (peeraddr);
peeraddr.sin_family=AF_INET;
peeraddr.sin_port=htons(1024);
// peeraddr.sin_addr.s_addr=INADDR_ANY;
peeraddr.sin_addr.s_addr=inet_addr( "172.16.10.120" );
// 这个地址是服务器的地址,
socklen_t addrLen;
addrLen = sizeof (peeraddr);
NSLog(@ "connecting" );
err=connect(fd, ( struct sockaddr *)&peeraddr, addrLen);
success=(err==0);
if (success) {
// struct sockaddr_in addr;
err =getsockname(fd, ( struct sockaddr *)&addr, &addrLen);
success=(err==0);
//============================================================================
//============================================================================
if (success) {
NSLog(@ "connect success,local address:%s,port:%d" ,inet_ntoa(addr.sin_addr),ntohs(addr.sin_port));
char buf[1024];
do {
printf ( "input message:" );
scanf ( "%s" ,buf);
send(fd, buf, 1024, 0);
} while ( strcmp (buf, "exit" )!=0);
}
}
else {
NSLog(@ "connect failed" );
}
}
// ============================================================================
//3
}
return 0;
|