文章目录
1,UNIX域套接字
用于本地进程间的通信
- socket同样可以用于本地通信
- 创建套接字时使用本地协议PF_UNIX(或PF_LOCAL)。
·socket(AF_LOCAL, SOCK_STREAM, 0) /流式套接字/
· socket(AF_LOCAL, SOCK_DGRAM, 0) /数据报套接字/
PF_INET 和 AF_INET的区别:http://blog.sina.com.cn/s/blog_8043547601013eoc.html
所以在windows中AF_INET与PF_INET完全一样
而在Unix/Linux系统中,在不同的版本中这两者有微小差别
对于BSD,是AF,对于POSIX是PF
- 分为流式套接字和用户数据报套接字
- 和其他进程间通信方式相比使用方便、效率更高
- 常用于前后台进程通信
Linux下的进程间通信机制 |
应用 |
早期UNIX进程间通信方式
(很多是从Unix继承的)
无名管道(pipe)
本地通信,用于一台计算机内部不同进程之间的通信
有名管道 (fifo)
信号(signal)
System V IPC
(系统5的IPC机制)
共享内存(share memory)
消息队列(message queue)
信号灯集(semaphore set)
套接字(socket)
既可以进行本地通信,更多的是多台主机之间通过网络通信
易用性:消息队列 > unix域套接字 > 管道 > 共享内存(经常要和信号量一起使用)
效率:共享内存 > unix域套接字 > 管道 > 消息队列
常用:共享内存、unix域套接字
异步通信:信号
同步和互斥(做资源保护):信号量
- 本地地址结构
struct sockaddr_un //
{
sa_family_t sun_family;
char sun_path[108]; // 套接字文件的路径
};
- 填充地址结构
struct sockaddr_un myaddr;
bzero(&myaddr, sizeof(myaddr));
myaddr.sun_family = AF_UNIX; strcpy(myaddr.sun_path, “/tmp/mysocket”);
2,UNIX域套接字模型
应用程序 |
UNIX域(流式)套接字 |
UNIX域(用户数据报)套接字 |
服务器端
客户端
#include
#include
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
- 此处addr是一个本地地址,结构体为struct sockaddr_un
#define UNIX_PATH_MAX 108
struct sockaddr_un {
sa_family_t sun_family;
char sun_path[UNIX_PATH_MAX];
};
- pathname 为域套接字的文件路径
·必须事先不存在(临时在内存中创建一个文件)
·一般是绝对路径
3,UNIX域套接字 — 示例
3.1,net.h
#ifndef __NET_H__
#define __NET_H__
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define UNIX_DOMAIN_FILE "/tmp/my_domain_file.1"
#define BACKLOG 5
#define QUIT_STR "quite"
#define SERV_RESP_STR "Server:"
#endif
3.2,client.c
#include "net.h"
void usage(char *s)
{
printf("Usage: %s
",s);
}
int main(int argc, const char *argv[])
{
int fd;
if(argc != 2)
{
usage((char *)argv[0]);
exit(1);
}
if((fd = socket(AF_LOCAL,SOCK_STREAM,0)) < 0)
{
perror("socket");
exit(-1);
}
struct sockaddr_un sun;
bzero(&sun,sizeof(sun));
sun.sun_family = AF_LOCAL;
if(access(UNIX_DOMAIN_FILE,F_OK|W_OK) < 0)
{
exit(-1);
}
strncpy(sun.sun_path,argv[1],strlen(argv[1]));
if(connect(fd,(struct sockaddr *)&sun,sizeof(sun)) < 0)
{
perror("connect");
goto _error1;
}
printf("client starung ... OK!
");
fd_set rset;
int maxfd;
struct timeval tout;
char buf[BUFSIZ];
int ret = -1;
while(1)
{
FD_ZERO(&rset);
FD_SET(0,&rset);
FD_SET(fd,&rset);
maxfd = fd;
tout.tv_sec = 5;
tout.tv_usec = 0;
select(maxfd+1,&rset,NULL,NULL,&tout);
if(FD_ISSET(0,&rset))
{
bzero(buf,BUFSIZ);
do
{
ret = read(0,buf,BUFSIZ-1);
}while(ret <0 && EINTR == errno);
if(ret < 0)
{
perror("read");
continue ;
}
if(ret == 0)
{
continue;
}
if(write(fd,buf,strlen(buf)) < 0)
{
perror("write() to socket");
continue ;
}
if(strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)) == 0)
{
printf("client is existung!
");
break;
}
}
if(FD_ISSET(fd,&rset))
{
bzero(buf,BUFSIZ);
do
{
ret = read(fd,buf,BUFSIZ-1);
}while(ret <0 && EINTR == errno);
if(ret < 0)
{
perror("read from socket");
continue ;
}
if(ret == 0)
{
break ;
}
printf("server said: %s",buf);
if((strlen(buf) > strlen(SERV_RESP_STR)) && strncasecmp(buf+strlen(SERV_RESP_STR),QUIT_STR,strlen(QUIT_STR)) == 0)
{
printf("sender client is existung!
");
break;
}
}
}
_error1:
close(fd);
return 0;
}
3.3,sever.c
#include "net.h"
#include "linklist.h"
#include
void do_select(int fd);
int main(int argc, const char *argv[])
{
int fd;
if((fd = socket(AF_LOCAL,SOCK_STREAM,0)) < 0)
{
perror("socket");
exit(-1);
}
int b_reuse = 1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int));
struct sockaddr_un sun;
bzero(&sun,sizeof(sun));
sun.sun_family = AF_LOCAL;
if(access(UNIX_DOMAIN_FILE,F_OK))
{
unlink(UNIX_DOMAIN_FILE);
}
strncpy(sun.sun_path,UNIX_DOMAIN_FILE,strlen(UNIX_DOMAIN_FILE));
if(bind(fd,(struct sockaddr *)&sun,sizeof(sun)))
{
perror("bind");
goto _error1;
}
if(listen(fd,BACKLOG) < 0)
{
perror("listen");
goto _error1;
}
do_select(fd);
_error1:
close(fd);
return 0;
}
void do_select(int fd)
{
linklist fdlist,sun_list;
fdlist = create_linklist();
datatype sun_data;
sun_data.fd = fd;
int maxfd = fd;
insert_end_linklist(fdlist,sun_data);
fd_set rset;
int newfd = -1;
int ret = -1;
char buf[BUFSIZ];
char resp_buf[BUFSIZ+10];
struct sockaddr_un cun;
socklen_t cun_addr_len = sizeof(cun);
while(1)
{
int i;
FD_ZERO(&rset);
if(get_length_linklist(fdlist) >= 1)
{
for(i=0;i<get_length_linklist(fdlist);i++)
{
sun_list = get_list_pos_linklist(fdlist,i);
sun_data = sun_list->data;
FD_SET(sun_data.fd,&rset);
maxfd = sun_data.fd > maxfd ? sun_data.fd : maxfd;
}
}
else
{
continue ;
}
switch(select(maxfd+1,&rset,NULL,NULL,NULL))
{
case 0:
{
printf("time out!
");
goto _error1;
}
case -1:
{
perror("select");
goto _error1;
}
default:
{
if(FD_ISSET(fd,&rset))
{
if((newfd = accept(fd,(struct sockaddr *)&cun,&cun_addr_len)) < 0)
{
perror("connect");
goto _error1;
}
int b_on = 1;
ioctl(newfd, FIONBIO, &b_on);
sun_data.fd = newfd;
printf("get a new client->(ip:%s)(port:%d)(fd:%d)
",sun_data.ipv4_addr,sun_data.port,sun_data.fd);
insert_end_linklist(fdlist,sun_data);
}
else
{
for(i=0;i<get_length_linklist(fdlist);i++)
{
sun_list = get_list_pos_linklist(fdlist,i);
sun_data = sun_list->data;
if(sun_data.fd == fd)
continue ;
bzero(buf,BUFSIZ);
do
{
ret = read(sun_data.fd,buf,BUFSIZ-1);
}while(ret < 0 && errno == EINTR);
if(ret < 0)
{
continue;
}
if(ret == 0)
{
printf("client is existung!
");
delete_locate_linklist(fdlist,sun_data);
continue;
}
printf("client ip(:%s) port(:%d) fd(:%d) receive data: %s",sun_data.ipv4_addr,sun_data.port,sun_data.fd,buf);
bzero(resp_buf,BUFSIZ+25);
strncpy(resp_buf,SERV_RESP_STR,strlen(SERV_RESP_STR));
strcat(resp_buf,"ip(");
strcat(resp_buf,sun_data.ipv4_addr);
char s_port[10];
strcat(resp_buf," port(");
sprintf(s_port,"%d",sun_data.port);
strcat(resp_buf,s_port);
strcat(resp_buf," data(");
strcat(resp_buf,buf);
do
{
ret = write(sun_data.fd,resp_buf,strlen(resp_buf));
}while(ret < 0 && EINTR == errno);
if(strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)) == 0)
{
printf("client (fd:%d)(ip:%s)(potr:%d) is existung!
",sun_data.fd,sun_data.ipv4_addr,sun_data.port);
delete_locate_linklist(fdlist,sun_data);
close(sun_data.fd);
}
}
}
}
}
}
close(newfd);
_error1:
close(fd);
clear_linklist(fdlist);
}
3.4,linklist.h
#ifndef __SINGLE_LINKLIST_H__
#define __SINGLE_LINKLIST_H__
#include
#include
#include
#include
typedef struct{
int fd;
char ipv4_addr[16];
int port;
}datatype;
typedef struct node{
datatype data;
struct node *next;
}listnode,*linklist;
linklist create_linklist(void);
linklist create_n_linklist(void);
int delete_pos_linklist(linklist L,int pos);
int delete_locate_linklist(linklist L,datatype x);
void clear_linklist(linklist L);
int get_length_linklist(linklist L);
linklist get_list_pos_linklist(linklist L,int pos);
linklist get_list_locate_linklist(linklist L,datatype x);
int insert_head_linklist(linklist L,datatype x);
int insert_n_head_linklist(linklist L);
int insert_end_linklist(linklist L,datatype x);
int insert_n_end_linklist(linklist L);
int insert_pos_linklist(linklist L,datatype x,int pos);
int insert_order_linklist(linklist L,datatype x);
void reverse_linklist(linklist);
void sort_linklist(linklist L);
void show_linklist(linklist L);
#endif
3.5,linklist.c
#include "linklist.h"
linklist create_linklist(void)
{
linklist L;
if((L=