> 文章列表 > C语言---Unix套接字用于本地通信

C语言---Unix套接字用于本地通信

C语言---Unix套接字用于本地通信

1、作用:用于本地间通信

2、使用:

        创建套接字的时候使用本地协议通信,AF_UNIX(或者AF_LOCAL),分为流式套接字和用户数据报套接字。

unix_socket = socket(AF_LOCAL, SOCK_STREAM, 0);
unix_socket = socket(AF_LOCAL, SOCK_DGRAM, 0);

3、进程间通信:(6种情况)

        3.1进程间数据共享:

                管道、消息队列、共享内存、unix套接字

                        易用性:消息队列>unix套接字>管道>共享内存(经常要和信号量一起用)

                        效率上:共享内存>unix套接字>管道>消息队列

                        共享内存相当于把一块内存从内核空间放到内存空间去操作。

                        效率上,常常共享内存和信号量一起使用,或者unix套接字。

        3.2异步通信:

                信号

        3.3同步和互斥:

                信号量       

4、Unix域套接字

/*本地地址结构*/#include <sys/un.h>
strcut sockaddr_in{sa_family_t sun_family; char sun_path[108];  //套接字文件的路径
};/*填充地址结构*/
strcut sockaddr_un myaddr;
bzero(&myaddr, sizeof(myaddr));
myaddr.sun_family = AF_UNIX;
strcpy(myaddr.sun_path, "/tmp/mysock");

5、

        5.1流式套接字服务器端

                socket(AF_UNIX, SOCK_STREAM, 0);

                bind(,本地地址,); //

                listen();

                accept();    //可以使用多路复用、多进程、多线程处理

                recv()  / send()

                close()

                注意:bind()函数详解

                        int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

                        之前互联网通信,这里绑定绑定的是通用地址结构体sockaddr。

                        现在本地通信,绑定的是sockaddr_un结构体,格式如下:     

//A UNIX domain socket address is represented in the following structure:#define UNIX_PATH_MAX    108struct sockaddr_un {sa_family_t sun_family;               /* AF_UNIX */char        sun_path[UNIX_PATH_MAX];  /* pathname */
};//sun_family always contains AF_UNIX  / AF_local
// unix_path_max  从96~108,是unix域套接字的文件路径名:
// 注意:1.这个文件(位于内存中)必须事先不存在;2.一般给绝对路径名;

        5.2流式套接字客户端  

                socket(AF_UNIX, SOCK_STREAM, 0);

                bind(,本地地址,); //

                listen();

                accept();    //可以使用多路复用、多进程、多线程处理

                recv()  / send()

                close()

6、实例代码

/*服务器:*/
void sig_child_handle(int signo){if(SIGCHLD == signo){//NULL:状态不许要,WNOHANG非阻塞方式waitpid(-1, NULL, WNOHANG);}   
}void cli_data_handle(int *arg);int main(int argc, char *argv[])
{//1.create socketint sockfd;//struct sockaddr_in sin;/*  typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);*/signal(SIGCHLD, sig_child_handle);if((sockfd = socket(AF_LOCAL, SOCK_STREAM, 0))<0){perror("create socket");return -1;}struct sockaddr_un sun;bzero(&sun, sizeof(sun));sun.sun_family = AF_UNIX;if(!access(UNIX_DOMAIN_FILE, F_OK)){unlink(UNIX_DOMAIN_FILE);}strncpy(sun.sun_path, UNIX_DOMAIN_FILE, strlen(UNIX_DOMAIN_FILE));if( ( bind(sockfd, (struct sockaddr *)(&sun), sizeof(sun)) ) == -1){perror("bind");exit(1);}
//3.listenif(listen(sockfd, BACKLOG)<0){perror("listen");exit(1);}printf("server start\\n");int newfd;while(1){pid_t pid = -1;if((newfd = accept(sockfd, NULL, NULL))<0){perror("accept");break;}//创建一个子进程,用于处理连接的客户端的交互数据if((pid = fork()) < 0){perror("fork");exit(1);}if(pid > 0){//父进程close(newfd);}else if(pid == 0){//子进程close(sockfd);cli_data_handle(&newfd);exit(1);}break;}//6.closeclose(sockfd);return 0;
}
void cli_data_handle(int *arg){int newfd = *(int *)arg;printf("child handling process:newfd=%d\\n", newfd);//5.write() 与newfd读写数据char buf[128];//char resp_buf[138];int ret = -1;while(1){bzero(buf, strlen(buf));do{ret = read(newfd, buf, 127);}while(ret<0 && errno==EINTR);if(ret < 0){perror("read");exit(1);}//客户端已经关闭if(!ret){break;}printf("recive data:%s\\n", buf);if( !strncasecmp(buf, QUIT_STR, strlen(QUIT_STR)) ){printf("client(%d) exiting\\n", newfd);break;}}close(newfd);
}

                

/*./client unix_domain_file */
#include "inet.h"void usage(char *s){printf("\\n%s unix_domain_file\\n", s); 
}int main(int argc, char *argv[])
{   if(argc != 2){ usage(argv[0]);exit(1);}   //1.create socketint sockfd;if((sockfd = socket(AF_LOCAL, SOCK_STREAM, 0))<0){perror("create socket");exit(1);}   
//2.连接服务器//填充sockaddr_in 结构体变量,struct sockaddr_un sun;bzero(&sun, sizeof(sun));sun.sun_family = AF_LOCAL;/*确保文件先存在并且可写,如果不存在,退出*/if(access(UNIX_DOMAIN_FILE, W_OK) < 0){exit(1);}strncpy(sun.sun_path, UNIX_DOMAIN_FILE, strlen(UNIX_DOMAIN_FILE));if(connect(sockfd, (struct sockaddr *)&sun, sizeof(sun)) < 0){perror("connect");exit(1);}printf("unix start....\\n");//3.read()读写数据int ret = -1;char buf[128];while(1){bzero(buf, 128);if(fgets(buf, 127, stdin) == NULL){continue;}do{ret = write(sockfd, buf, strlen(buf));}while(ret<0 && errno==EINTR);if(! strncasecmp(buf, QUIT_STR, strlen(buf)-1)){printf("client is exiting\\n");break;}}//4.close()关闭套接字close(sockfd);return 0;
}