域套接字使用方式和TCP/IP一样:
相比共享内存而言,它是主动发数据,被动收数据,拥有阻塞和非阻塞模式以及它们之间的切换。
域套接字传输稳定,无论是否建立连接,都不会发生丢包的情况。同时,它的传输速度比本地环回快很多。
域套接字如同TCP/IP一样,也分为流(SOCK_STREAM)和数据包(SOCK_DGRAM),采用流传输时也需要解决粘包问题。
如果在文件系统中,已经有了一个文件和指定的路径名相同,则绑定会失败(返回错误EADDRINUSE)。所以,一个套接字只能绑定到一个路径上,同样的,一个路径也只能被一个套接字绑定。
服务器端:
#include "../common.h"
#define FILE_PATH "./my_socket"
int main()
{
int serFd,cliFd;
int ret = -1;
struct sockaddr_un s_addr,c_addr;
char buffer[1024] = {0};
serFd = socket(AF_UNIX,SOCK_STREAM,0); //为SOCK_STREAM时仍需处理粘包问题
if(serFd < 0)
{
perror("socket");
return -1;
}
s_addr.sun_family = AF_UNIX;
int addr_len = sizeof(s_addr);
strcpy(s_addr.sun_path,FILE_PATH);
unlink(FILE_PATH);
if( bind(serFd,(struct sockaddr*)&s_addr,sizeof(s_addr)) < 0)
{
perror("bind");
return -1;
}
if(listen(serFd,5) < 0)
{
perror("listen");
return -1;
}
fd_set ser_set, rser_set;
FD_ZERO(&ser_set);
FD_SET(serFd, &ser_set);
int maxfd = serFd;
struct timeval tv0;
while(true)
{
rser_set = ser_set;
printf("wait select ....\n");
tv0.tv_sec = 5;
tv0.tv_usec = 0;
ret = select(maxfd + 1, &rser_set, NULL, NULL,NULL); //对读进行操作等待(NULL无限等待)
if (ret == 0)
{
printf("select ret == 0 ....\n");
continue;
}
if (ret < 0)
{
perror("select");
sleep(1);
continue;
}
if (FD_ISSET(serFd, &rser_set))
{
if (cliFd > 0)
{
close(cliFd);
cliFd = -1;
}
cliFd = accept(serFd, NULL, NULL);
if (cliFd < 0)
{
perror("accept");
continue;
}
printf("\nrecv client_fd data ...\n");
if (cliFd > maxfd)
{
maxfd = cliFd;
}
FD_SET(cliFd, &ser_set);
}
else
{
if (cliFd < 0)
continue;
memset(buffer, 0, 4096);
int iDataNum = recv(cliFd, buffer, 4096, MSG_DONTWAIT);
if (iDataNum <= 0)
{
FD_CLR(cliFd, &ser_set);
if (iDataNum < 0)
{
perror("recv");
}
else
{
if (cliFd > 0)
{
close(cliFd);
}
cliFd = -1;
}
continue;
}
else
{
printf("buffer form cli: '%s' iDataNum:%d\n", buffer,iDataNum);
}
}
}
close(serFd);
if(cliFd > 0)close(cliFd);
return 0;
}
客户端:
#include "../common.h"
#define FILE_PATH "./my_socket"
int main()
{
int fd;
int ret = -1;
struct sockaddr_un s_addr;
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if(fd < 0)
{
perror("socket");
return -1;
}
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path,FILE_PATH);
if(connect(fd,(struct sockaddr*)&s_addr,sizeof(s_addr)) < 0)
{
perror("connect");
};
char buf[1024] = "I'm client";
while(true)
{
ret = write(fd,buf,strlen(buf)+1); //与TCP一样
printf("write ret = %d\n",ret);
if(ret < 0)break;
}
close(fd);
}
结果展示:
wait select ....
buffer form cli: I'm client iDataNum:44
wait select ....
buffer form cli: I'm client iDataNum:22
wait select ....
buffer form cli: I'm client iDataNum:22
wait select ....
buffer form cli: I'm client iDataNum:33
wait select ....
buffer form cli: I'm client iDataNum:22
wait select ....
buffer form cli: I'm client iDataNum:22
wait select ....
buffer form cli: I'm client iDataNum:22
wait select ....
buffer form cli: I'm client iDataNum:22
wait select ....
buffer form cli: I'm client iDataNum:22
wait select ....
buffer form cli: I'm client iDataNum:33
wait select ....
buffer form cli: I'm client iDataNum:22
wait select ....
buffer form cli: I'm client iDataNum:22
wait select ....
可以看到有粘包存在(因为是字符串,所以打印结果是正确的)