16.unix域協議
一.Unix域協議
Uinx域套接字有幾個理由:
UNIX域套接字用於在同一臺機器上執行的程式之間的通訊。雖然因特網域套接字也可以達到同一目的,但UNIX域套接字的效率更高。
UNIX域套接字僅僅複製資料;它們並不執行協議處理,不需要新增或刪除網路報頭,無需計算檢驗和,不要產生順序號,無需傳送確認報文。
UNIX域套接字提供流和資料包兩種介面。
UNIX域資料包服務是可靠的,既不會丟失訊息也不會傳遞出錯。
UNIX域套接字是套接字和管道之間的混合物。為了建立一對非命名的、相互連線的UNIX域套接字,使用者可以使用它們面向網路的域套接字介面,也可使用socketpair函式。
UNIX域套接字可用在同一個主機上的不同程式之間傳遞描述符.
在<sys/un.h>中有定義Unix域套接字地址結構,在ubuntu中的路徑為:/usr/include/linux/un.h
struct sockaddr_un {
__kernel_sa_family_t sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
};
二.利用Unix域協議實現回射C/S伺服器
echoser.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
void echo_ser(int conn)
{
char recvbuf[1024];
int n;
while(1)
{
bzero(recvbuf,sizeof(recvbuf));
n = read(conn,recvbuf,sizeof(recvbuf));
if(n==-1)
{
if(n == EINTR) // 由於訊號中斷,沒讀到任何資料。
continue;
ERR_EXIT("read err");
}
else if(n == 0)
{
printf("client close\n");
break;
}
fputs(recvbuf,stdout);
write(conn,recvbuf,strlen(recvbuf));
}
close(conn);
}
int main()
{
int listenfd;
if( (listenfd = socket(AF_UNIX,SOCK_STREAM,0)) < 0)
ERR_EXIT("socket err");
unlink("/tmp/test_socket"); // 刪除檔案
struct sockaddr_un servaddr;
bzero(&servaddr,sizeof(servaddr));
servaddr.sun_family = AF_UNIX;
strcpy(servaddr.sun_path,"/tmp/test_socket");
if( bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
ERR_EXIT("bind err");
if( listen(listenfd,SOMAXCONN) < 0)
ERR_EXIT("listen err");
int conn;
pid_t pid;
while(1)
{
conn = accept(listenfd,NULL,NULL);
if(conn == -1)
{
if(conn == EINTR)
continue;
ERR_EXIT("accept err");
}
pid = fork();
if(pid == -1)
ERR_EXIT("fork err");
if(pid == 0) // 子程式,不需要處理監聽
{
close(listenfd);
echo_ser(conn);
exit(EXIT_SUCCESS);
}
// 父程式
close(conn); // 父程式不需要已連線套接字
}
}
echocli.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
void echo_cli(int sock)
{
char sendbuf[1024] = {0};
char recvbuf[1024] = {0};
while(fgets(sendbuf,sizeof(sendbuf),stdin) != NULL)
{
// 傳送資料
write(sock,sendbuf,strlen(sendbuf));
//接收資料
read(sock,recvbuf,sizeof(recvbuf));
// 列印接收緩衝區的資料
fputs(recvbuf,stdout);
// 緩衝區清空
bzero(sendbuf,sizeof(sendbuf));
bzero(recvbuf,sizeof(recvbuf));
}
}
int main()
{
int sock;
if ((sock = socket(AF_UNIX,SOCK_STREAM,0))<0)
ERR_EXIT("socket err");
struct sockaddr_un servaddr;
bzero(&servaddr,sizeof(servaddr));
servaddr.sun_family = AF_UNIX;
strcpy(servaddr.sun_path,"/tmp/test_socket");
if(connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
ERR_EXIT("connect err");
echo_cli(sock);
return 0;
}
三.Unix域協議程式設計要點
(1)bind 成功時將建立一個檔案,許可權為0777 & ~umask
(2)sun_path 最好用一個絕對路徑
(3)UNIX域協議支援流式套接字與報文套接字
(4)UNIX域流式套接字connect發現監聽佇列滿時立刻返回一個ECONNREFUSED,這和TPC不同,如果監聽佇列滿,會忽略到來的SYN,這導致對方重傳SYN
相關文章
- 域滲透之ldap協議LDA協議
- 【安全科普】AD域安全協議(四)RPC協議RPC
- 《Unix 網路程式設計》15:Unix 域協議程式設計協議
- Raft協議和ZAB協議Raft協議
- OSPF協議的多區域配置,圖文講解協議
- Gossip協議也叫Epidemic協議(流行病協議)Go協議IDE
- zigbee協議的缺點 zigbee的主要應用領域協議
- HCNA Routing&Switching之廣域網協議HDLC和PPP協議
- 頁面連結跳轉--指定協議,半協議,無協議協議
- 協議協議
- 淺談WebSocket協議、WS協議和WSS協議原理及關係Web協議
- Gossip協議和Grpc協議的區別Go協議RPC
- 系列TCP/IP協議-TCP協議概述(011)TCP協議
- 二進位制協議 VS 文字協議協議
- 匯流排協議系列——USART協議初探協議
- 生成樹協議與多生成樹協議協議
- XModem協議協議
- swift協議Swift協議
- UART協議協議
- SPI協議協議
- WebSocket協議Web協議
- 協議號協議
- ICMP協議協議
- OSPF協議協議
- Memcached 協議協議
- HTTPS 協議HTTP協議
- ipad協議iPad協議
- mysql協議MySql協議
- rpc協議RPC協議
- Modbus協議協議
- CAN協議協議
- usb協議協議
- signal協議協議
- BGP協議協議
- http協議HTTP協議
- TCP協議TCP協議
- PAOXS協議協議
- HTTP 協議HTTP協議
- raft協議Raft協議