数据包形式和UDP并不完全一样,在UDP中,服务器可以在接收到客户端的消息之后给与客户端回应。但是在域套接字中,这是不被允许的,
因为域套接字不像UDP那样封装了包头等协议可用于解析出地址。所以在数据包形式中,如果要实现这种双向通信,客户端也必须要绑定一个地址。
服务端示例代码:
#include "../common.h"
#define FILE_PATH_SER "./my_socket_s"
#define FILE_PATH_CLI "./my_socket_c"
int main()
{
int serFd,cliFd;
struct sockaddr_un s_addr,c_addr;
char recvbuf[1024] = {0};
char sendbuf[1024] = {0};
int ret = -1;
int addrLen = sizeof(s_addr);
if((serFd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
{
printf("socket serFd fail\n");
return 0;
}
if((cliFd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
{
printf("socket cliFd fail\n");
return 0;
}
unlink(FILE_PATH_SER); //删除文件,保证文件不存在
memset(&s_addr, 0, sizeof(struct sockaddr_un));
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path,FILE_PATH_SER);
c_addr.sun_family = AF_UNIX;
strcpy(c_addr.sun_path,FILE_PATH_CLI);
//必须绑定
if(bind(serFd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr)) == -1)
{
printf("bind fail\n");
return 0;
}
while(1)
{
ret = recvfrom(serFd, recvbuf, 1024, 0,(struct sockaddr *)&s_addr, (socklen_t*)&addrLen);
if(ret < 0)
{
char *errorMsg = strerror(errno);
printf("recv from cli fail:%s\n", errorMsg);
break;
}
printf("recv '%s' from cli ...\n",recvbuf);
sprintf(sendbuf,"ser recv '%s'",recvbuf);
ret = sendto(cliFd,sendbuf, 1024, 0,(struct sockaddr *)&c_addr, sizeof(struct sockaddr));
if(ret < 0)
{
char *errorMsg = strerror(errno);
printf("send to cli fail:%s\n", errorMsg);
break;
}
else
{
printf("send '%s' to cli success ...\n\n",sendbuf);
}
}
close(serFd);
close(cliFd);
}
客户端:
#include "../common.h"
#define FILE_PATH_SER "./my_socket_s"
#define FILE_PATH_CLI "./my_socket_c"
/*
按照普通的包套接字创建和连接的流程,只是在服务器端调用bind()函数绑定了一个地址,而客户端并没有地址。
这在流式套接字中没有问题,内核已经在服务器端调用accept()函数接收一个客户端连接时创建了一个新的套接字,
从而将一一对应关系绑定到了这个新的套接字上了。所以,对于包套接字来说,
在客户端还需要再调用bind()函数绑定一次,人为的创建一个客户端地址,且这个客户端路径名地址显然不能和服务器端的路径名相同。
这样看来,并没有实际的客户端与服务器之分.
*/
int main()
{
int serFd,cliFd;
struct sockaddr_un s_addr,c_addr;
int ret = -1;
char sendbuf[1024];
char recvbuf[1024];
int addrLen = sizeof(s_addr);
if((serFd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
{
printf("socket serFd fail\n");
return 0;
}
if((cliFd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
{
printf("socket cliFd fail\n");
return 0;
}
memset(&s_addr, 0, sizeof(struct sockaddr_un));
memset(&c_addr, 0, sizeof(struct sockaddr_un));
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path,FILE_PATH_SER);
c_addr.sun_family = AF_UNIX;
strcpy(c_addr.sun_path,FILE_PATH_CLI);
unlink(FILE_PATH_CLI);
if(bind(cliFd, (struct sockaddr *)&c_addr, sizeof(struct sockaddr)) == -1)
{
printf("bind fail\n");
return 0;
}
while(1)
{
printf("please input send message:");
scanf("%s",sendbuf);
getchar();
if((ret = sendto(serFd, sendbuf, 1024, 0,(struct sockaddr *)&s_addr, sizeof(struct sockaddr))) < 0)
{
char *errorMsg = strerror(errno);
printf("send to ser fail:%s\n", errorMsg);
break;
}
printf("send '%s' to ser success ...\n",sendbuf);
ret = recvfrom(cliFd, recvbuf, 1024, 0,(struct sockaddr *)&c_addr, (socklen_t*)&addrLen);
if(ret < 0)
{
char *errorMsg = strerror(errno);
printf("recv from ser fail:%s\n", errorMsg);
break;
}
else
{
printf("recv (%s) from ser ...\n\n",recvbuf);
}
}
close(serFd);
close(cliFd);
}
结果展示: