socket進程通信與網(wǎng)絡通信使用的是統(tǒng)一套接口,,只是地址結(jié)構(gòu)與某些參數(shù)不同。 一,。創(chuàng)建socket服務端的流程如下: (1)創(chuàng)建socket,類型為AF_LOCAL或AF_UNIX,,表示用于進程通信: - int server_fd;
- int client_fd;
- struct sockaddr_un server_addr;
- struct sockaddr_un client_addr;
- size_t server_len,client_len;
-
-
-
- unlink(SERVER_NAME);
- if ((server_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
- perror("socket");
- exit(1);
- }
(2)命名socket,。這里面有一個很關(guān)鍵的東西,,socket進程通信命名方式有兩種。一是普通的命名,,socket會根據(jù)此命名創(chuàng)建一個同名的socket文件,,客戶端連接的時候通過讀取該socket文件連接到socket服務端。這種方式的弊端是服務端必須對socket文件的路徑具備寫權(quán)限,,客戶端必須知道socket文件路徑,且必須對該路徑有讀權(quán)限,。另外一種命名方式是抽象命名空間,,這種方式不需要創(chuàng)建socket文件,,只需要命名一個全局名字,,即可讓客戶端根據(jù)此名字進行連接,。后者的實現(xiàn)過程與前者的差別是,,后者在對地址結(jié)構(gòu)成員sun_path數(shù)組賦值的時候,必須把第一個字節(jié)置0,,即sun_path[0] = 0,,下面用代碼說明:第一種方式:
-
- server_addr.sun_family = AF_UNIX;
- strcpy(server_addr.sun_path,SERVER_NAME);
- server_len = sizeof(struct sockaddr_un);
- client_len = server_len;
第二種方式:
-
- server_addr.sun_family = AF_UNIX;
- strcpy(server_addr.sun_path, SERVER_NAME);
- server_addr.sun_path[0]=0;
-
- server_len = strlen(SERVER_NAME) + offsetof(struct sockaddr_un, sun_path);
其中,,offsetof函數(shù)在#include <stddef.h>頭文件中定義,。因第二種方式的首字節(jié)置0,我們可以在命名字符串SERVER_NAME前添加一個占位字符串,例如:
- #define SERVER_NAME @socket_server
前面的@符號就表示占位符,,不算為實際名稱。 或者可以把第二種方式的實現(xiàn)封裝成一個函數(shù):
- int makeAddr(const char* name, struct sockaddr_un* pAddr, socklen_t* pSockLen)
- {
- int nameLen = strlen(name);
- if (nameLen >= (int) sizeof(pAddr->sun_path) -1)
- return -1;
- pAddr->sun_path[0] = '\0';
- strcpy(pAddr->sun_path+1, name);
- pAddr->sun_family = AF_UNIX;
- *pSockLen = 1 + nameLen + offsetof(struct sockaddr_un, sun_path);
- return 0;
- }
像下面這樣使用這個函數(shù):
- makeAddr("server_socket", &server_addr, &server_len);
提示:客戶端連接服務器的時候,必須與服務端的命名方式相同,,即如果服務端是普通命名方式,客戶端的地址也必須是普通命名方式,;如果服務端是抽象命名方式,客戶端的地址也必須是抽象命名方式,。(3)綁定并偵聽
- bind(server_sockfd, (struct sockaddr *)&server_addr, server_len);
-
-
- listen(server_sockfd, 5);
(4)等待客戶端連接,,并讀寫數(shù)據(jù)。
- while(1){
- printf("server waiting...\n");
-
-
- client_len = sizeof(client_addr);
- client_sockfd = accept(server_sockfd,(struct sockaddr*)&client_addr, &client_len);
-
-
- read(client_sockfd, &ch, 1);
- printf("read from client %d: %c",client_sockfd,ch);
- ch ++;
- write(client_sockfd, &ch, 1);
- close(client_sockfd);
- usleep(100);
- }
二 socket客戶端創(chuàng)建流程(1)創(chuàng)建socket (2)命名socket (3)連接到服務端:
-
- result = connect(sockfd, (struct sockaddr*)&address, len);
(4)與服務端進行通信
-
- while(1)
- {
- printf("set send content:");
- scanf("%c",&ch);
- write(sockfd, &ch, 1);
- printf("send to server:%c \n",ch);
- read(sockfd, &ch, 1);
- printf("read from server: %c\n", ch);
-
-
- }
完整代碼如下:(1)服務端server.c:
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<stdio.h>
- #include<sys/un.h>
- #include<unistd.h>
- #include<stdlib.h>
- #include <stddef.h>
-
- #define SERVER_NAME "@server_socket"
-
-
-
-
-
-
- int makeAddr(const char* name, struct sockaddr_un* pAddr, socklen_t* pSockLen)
- {
- int nameLen = strlen(name);
- if (nameLen >= (int) sizeof(pAddr->sun_path) -1)
- return -1;
- pAddr->sun_path[0] = '\0';
- strcpy(pAddr->sun_path+1, name);
- pAddr->sun_family = AF_UNIX;
- *pSockLen = 1 + nameLen + offsetof(struct sockaddr_un, sun_path);
- return 0;
- }
-
- int main()
-
- {
- int server_sockfd, client_sockfd;
- socklen_t server_len, client_len;
- struct sockaddr_un server_addr;
- struct sockaddr_un client_addr;
- char ch;
- int nread;
-
-
-
-
- server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
-
-
- server_addr.sun_family = AF_UNIX;
- strcpy(server_addr.sun_path, SERVER_NAME);
- server_addr.sun_path[0]=0;
-
- server_len = strlen(SERVER_NAME) + offsetof(struct sockaddr_un, sun_path);
-
- bind(server_sockfd, (struct sockaddr *)&server_addr, server_len);
-
-
- listen(server_sockfd, 5);
- client_sockfd = -1;
- client_len = sizeof(client_addr);
- while(1){
- printf("server waiting...\n");
-
- if(client_sockfd == -1){
- client_sockfd = accept(server_sockfd,(struct sockaddr*)&client_addr, &client_len);
- }
-
-
- nread = read(client_sockfd, &ch, 1);
- if(nread == 0){
- printf("client %d disconnected\n",client_sockfd);
- client_sockfd = -1;
- }
- else{
- printf("read from client %d: %c\n",client_sockfd,ch);
- ch ++;
- write(client_sockfd, &ch, 1);
- }
- usleep(100);
- }
-
- return 0;
-
- }
(2)客戶端client.c
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<stdio.h>
- #include<sys/un.h>
- #include<unistd.h>
- #include<stdlib.h>
- #include <stddef.h>
- #define SERVER_NAME "@server_socket"
-
-
-
-
-
-
- int makeAddr(const char* name, struct sockaddr_un* pAddr, socklen_t* pSockLen)
- {
- int nameLen = strlen(name);
- if (nameLen >= (int) sizeof(pAddr->sun_path) -1)
- return -1;
- pAddr->sun_path[0] = '\0';
- strcpy(pAddr->sun_path+1, name);
- pAddr->sun_family = AF_UNIX;
- *pSockLen = 1 + nameLen + offsetof(struct sockaddr_un, sun_path);
- return 0;
- }
-
-
- int main()
- {
- int sockfd;
- socklen_t len;
- struct sockaddr_un address;
- int result;
- char ch = 'A';
-
-
- sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
-
-
- address.sun_family = AF_UNIX;
- strcpy(address.sun_path, SERVER_NAME);
- address.sun_path[0]=0;
-
- len = strlen(SERVER_NAME) + offsetof(struct sockaddr_un, sun_path);
-
- result = connect(sockfd, (struct sockaddr*)&address, len);
- if(result == -1)
- {
- perror("opps:client1");
- exit(1);
- }
-
- while(1)
- {
- printf("set send content:");
- scanf("%c",&ch);
- write(sockfd, &ch, 1);
- printf("send to server:%c \n",ch);
- read(sockfd, &ch, 1);
- printf("read from server: %c\n", ch);
-
-
- }
- exit(0);
-
- }
|