常用的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; |