UNIX域套接字
以下大部分來自:https://www.cnblogs.com/xcywt/p/8185597.html
——————————————————————————————
?
?
?
?
1.什么是UNIX域套接字
Unix域協(xié)議并不是一個(gè)實(shí)際的協(xié)議族,而是在單個(gè)主機(jī)上執(zhí)行客戶/服務(wù)通信的一種方式。是進(jìn)程間通信(IPC)的一種方式。
它提供了兩類套接字:字節(jié)流套接字(有點(diǎn)像TCP)和數(shù)據(jù)報(bào)套接字(有點(diǎn)像UDP)
UNIX域數(shù)據(jù)報(bào)服務(wù)是可靠的,不會(huì)丟失消息,也不會(huì)傳遞出錯(cuò)。
IP協(xié)議標(biāo)識(shí)客戶服務(wù)器是通過IP地址和端口號(hào)實(shí)現(xiàn)的,UNIX域協(xié)議中用于標(biāo)識(shí)客戶機(jī)和服務(wù)器的協(xié)議地址的是普通文件系統(tǒng)中的路徑名。
2.UNIX域協(xié)議特點(diǎn)
1)UNIX域套接字域TCP套接字相比,在同一臺(tái)主機(jī)的傳輸速度前者是后者的兩倍。UNIX域套接字僅僅復(fù)制數(shù)據(jù),并不執(zhí)行協(xié)議處理,不需要添加或刪除網(wǎng)絡(luò)報(bào)頭,無需計(jì)算校驗(yàn)和,不產(chǎn)生順序號(hào),也不需要發(fā)送確認(rèn)報(bào)文
2)UNIX域套接字可以在同一臺(tái)主機(jī)上各進(jìn)程之間傳遞文件描述符
3)UNIX域套接字域傳統(tǒng)套接字的區(qū)別是用路徑名表示協(xié)議族的描述
下面是我的代碼:
#include<stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include<iostream> #include<sys/un.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include<sys/select.h> #include<errno.h> #include<sys/signal.h> using namespace std; void handler(int sig){cout<<sig<<endl; } int main() { signal(SIGPIPE,SIG_IGN);//signal(SIGPIPE,handler);int sockfd = socket(PF_UNIX, SOCK_STREAM, 0);unlink("test_socket");if (sockfd == -1){perror("socket() err");return -1;}int on = 1;if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1){perror("setsockopt() err");return -1;}int conn;struct sockaddr_un addr;memset(&addr,0,sizeof(addr));addr.sun_family=AF_UNIX;strcpy(addr.sun_path,"test_socket");if (bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1){perror("bind() err");return -1;}if (listen(sockfd, SOMAXCONN) == -1){perror("bind() err");return -1;}pid_t pid;while (1){ conn=accept(sockfd,NULL,NULL);pid=fork();if(pid==0){close(sockfd);char recvbuf[1024];while(1){int rc = read(conn, recvbuf, sizeof(recvbuf));if (rc == 0){printf("client is closed !\n");break;} else if (rc < 0){printf("read() failed ! error message:%s\n", strerror(errno));break;}printf("recv message:%s\n", recvbuf);write(conn, recvbuf, rc);memset(recvbuf, 0, sizeof(recvbuf));}close(conn);exit(EXIT_SUCCESS);//記得退出子進(jìn)程,否則子進(jìn)程將會(huì)無限循環(huán)read錯(cuò)誤 }close(conn);}return 0; } server.cpp #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include<sys/select.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include<iostream> #include<sys/un.h> using namespace std; int main(){ int sockfd = socket(PF_UNIX, SOCK_STREAM, 0);if (sockfd == -1){perror("socket() err");return -1;}struct sockaddr_un addr;addr.sun_family = AF_UNIX;strcpy(addr.sun_path,"test_socket");if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1){perror("socket() err");return -1;}char sendbuf[1024]={0};char recvbuf[1024]={0};while(fgets(sendbuf,sizeof(sendbuf),stdin)!=NULL){//sendwrite(sockfd,sendbuf,sizeof(sendbuf));//recvint rc=read(sockfd,recvbuf,sizeof(recvbuf));if(rc<0){perror("read() error");break;}else if(rc==0){printf("connect is cloesd !\n");break;}printf("recv message:%s\n",recvbuf);memset(sendbuf,0,sizeof(sendbuf));memset(recvbuf,0,sizeof(recvbuf));}close(sockfd);return 0; }?
?
在Linux中第一個(gè)字符代表這個(gè)文件是目錄、文件或鏈接文件等等。
- 當(dāng)為[?d?]則是目錄
- 當(dāng)為[?-?]則是文件;
- 若是[?l?]則表示為鏈接文檔(link file);
- 若是[?b?]則表示為裝置文件里面的可供儲(chǔ)存的接口設(shè)備(可隨機(jī)存取裝置);
- 若是[?c?]則表示為裝置文件里面的串行端口設(shè)備,例如鍵盤、鼠標(biāo)(一次性讀取裝置)。
?
1)啟動(dòng)server后,bind后會(huì)在對(duì)應(yīng)目錄創(chuàng)建一個(gè)文件(權(quán)限是0777&~umask)。這文件的類型是s。表示是套接口文件。可以通過ls -al查看。
2)若套接口文件存在,則bind會(huì)出錯(cuò)。為此可以先把該文件刪掉。(server中的unlink就干這個(gè)的)
3)創(chuàng)建的套接口文件最好為絕對(duì)路徑。建議指定在/tmp目錄下。比如把上面的目錄改成/tmp/test_socket
3)UNIX域流式套接字connect發(fā)現(xiàn)監(jiān)聽隊(duì)列滿時(shí),會(huì)立刻返回一個(gè)ECONNREFUSED,這和TCP不同,如果監(jiān)聽隊(duì)列滿了,會(huì)忽略到來的SYN,這會(huì)導(dǎo)致對(duì)方重傳SYN。
轉(zhuǎn)載于:https://www.cnblogs.com/illfuckingkyzb/p/10186813.html
總結(jié)
- 上一篇: 弱类型、强类型、动态类型、静态类型语言的
- 下一篇: Annihilate(SA)