域套接字简介及范例(二)————数据包形式

数据包形式和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);
}

结果展示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值