套接字是一種通信機(jī)制,憑借這種機(jī)制,客戶/服務(wù)器系統(tǒng)的開(kāi)發(fā)工作既可以在本地單機(jī)上進(jìn)行,也可以跨網(wǎng)絡(luò)進(jìn)行。
套接字的特性有三個(gè)屬性確定,它們是:域(domain),類型(type),和協(xié)議(protocol)。套接字還用地址作為它的名字。地址的格式隨域(又被稱為協(xié)議族,protocol family)的不同而不同。每個(gè)協(xié)議族又可以使用一個(gè)或多個(gè)地址族定義地址格式。
1.套接字的域
域指定套接字通信中使用的網(wǎng)絡(luò)介質(zhì)。最常見(jiàn)的套接字域是AF_INET,它是指Internet網(wǎng)絡(luò),許多Linux局域網(wǎng)使用的都是該網(wǎng)絡(luò),當(dāng)然,因特網(wǎng)自身用的也是它。其底層的協(xié)議——網(wǎng)際協(xié)議(IP)只有一個(gè)地址族,它使用一種特定的方式來(lái)指定網(wǎng)絡(luò)中的計(jì)算機(jī),即IP地址。
在計(jì)算機(jī)系統(tǒng)內(nèi)部,端口通過(guò)分配一個(gè)唯一的16位的整數(shù)來(lái)表示,在系統(tǒng)外部,則需要通過(guò)IP地址和端口號(hào)的組合來(lái)確定。
2.套接字類型
流套接字(在某些方面類似域標(biāo)準(zhǔn)的輸入/輸出流)提供的是一個(gè)有序,可靠,雙向字節(jié)流的連接。
流套接字由類型SOCK_STREAM指定,它們是在AF_INET域中通過(guò)TCP/IP連接實(shí)現(xiàn)的。他們也是AF_UNIX域中常見(jiàn)的套接字類型。
數(shù)據(jù)包套接字
與流套接字相反,由類型SOCK_DGRAM指定的數(shù)據(jù)包套接字不建立和維持一個(gè)連接。它對(duì)可以發(fā)送的數(shù)據(jù)包的長(zhǎng)度有限制。數(shù)據(jù)報(bào)作為一個(gè)單獨(dú)的網(wǎng)絡(luò)消息被傳輸,它可能會(huì)丟失,復(fù)制或亂序到達(dá)。
數(shù)據(jù)報(bào)套接字實(shí)在AF_INET域中通過(guò)UDP/IP連接實(shí)現(xiàn),它提供的是一種無(wú)需的不可靠服務(wù)。
3.套接字協(xié)議
只要底層的傳輸機(jī)制允許不止一個(gè)協(xié)議來(lái)提供要求的套接字類型,我們就可以為套接字選擇一個(gè)特定的協(xié)議。
先上一個(gè)代碼
服務(wù)端:
//s_unix.c #include#include #include #include #define UNIX_DOMAIN "/tmp/UNIX.domain" int main(void) { socklen_t clt_addr_len; int listen_fd; int com_fd; int ret; int i; static char recv_buf[1024]; int len; struct sockaddr_un clt_addr; struct sockaddr_un srv_addr; listen_fd=socket(PF_UNIX,SOCK_STREAM,0); if(listen_fd<0) { perror("cannot create communication socket"); return 1; } //set server addr_param srv_addr.sun_family=AF_UNIX; strncpy(srv_addr.sun_path,UNIX_DOMAIN,sizeof(srv_addr.sun_path)-1); unlink(UNIX_DOMAIN); //bind sockfd & addr ret=bind(listen_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr)); if(ret==-1) { perror("cannot bind server socket"); close(listen_fd); unlink(UNIX_DOMAIN); return 1; } //listen sockfd ret=listen(listen_fd,1); if(ret==-1) { perror("cannot listen the client connect request"); close(listen_fd); unlink(UNIX_DOMAIN); return 1; } //have connect request use accept len=sizeof(clt_addr); com_fd=accept(listen_fd,(struct sockaddr*)&clt_addr,&len); if(com_fd<0) { perror("cannot accept client connect request"); close(listen_fd); unlink(UNIX_DOMAIN); return 1; } //read and printf sent client info printf("/n=====info=====/n"); for(i=0;i<4;i++) { memset(recv_buf,0,1024); int num=read(com_fd,recv_buf,sizeof(recv_buf)); printf("Message from client (%d)) :%s/n",num,recv_buf); } close(com_fd); close(listen_fd); unlink(UNIX_DOMAIN); return 0; }